RxJava 作为事件总线?

RxJava as event bus?

我开始学习 RxJava,到目前为止我很喜欢它。我有一个片段在单击按钮时与 activity 通信(用新片段替换当前片段)。 Google 建议使用 interface 来让片段与 activity 进行通信,但它太冗长了,我尝试使用广播接收器,它可以正常工作,但它有缺点。

自从我学习 RxJava 以来,我想知道从片段到活动(或片段到片段)进行通信是否是一个好的选择?如果是这样,使用 RxJava 进行此类通信的最佳方式是什么?我是否需要制作这样的事件总线 one 如果是这样,我是否应该制作一个总线实例并在全球范围内使用它(与主题一起使用)?

是的,在你学会如何做之后,它会非常棒。考虑以下单例 class:

public class UsernameModel {

    private static UsernameModel instance;

    private PublishSubject<String> subject = PublishSubject.create();

    public static UsernameModel instanceOf() {
        if (instance == null) {
            instance = new UsernameModel();
        }
        return instance;
    }

    /**
     * Pass a String down to event listeners.
     */
    public void setString(String string) {
        subject.onNext(string);
    }

    /**
     * Subscribe to this Observable. On event, do something e.g. replace a fragment
     */
    public Observable<String> getStringObservable() {
        return subject;
    }

}

在您的 Activity 中准备好接收事件(例如在 onCreate 中):

UsernameModel usernameModel = UsernameModel.instanceOf();

//be sure to unsubscribe somewhere when activity is "dying" e.g. onDestroy
subscription = usernameModel.getStringObservable()
        .subscribe(s -> {
            // Do on new string event e.g. replace fragment here
        }, throwable -> {
            // Normally no error will happen here based on this example.
        });

在你的 Fragment 中传递发生的事件:

UsernameModel.instanceOf().setString("Nick");

你的 activity 然后会做一些事情。

提示 1:将字符串更改为您喜欢的任何对象类型。

技巧 2:如果你有依赖注入,它也很有效。


更新: 我写的比较长article

目前我认为我对这个问题的首选方法是:

1.) 使用 "local" 总线来明确定义目的,而不是使用一个全局总线来处理整个应用程序中的所有内容(因此变得非常笨拙),并且只将它们插入您需要的地方。

例如你可能有:

  • 用于在您的 ActivityApiService 之间发送数据的总线。
  • 一个总线用于在 Activity 中的多个 Fragment 之间进行通信。
  • 将当前选择的应用程序主题颜色发送到所有 Activity 的总线,以便它们可以相应地为所有图标着色。

2.) 使用 Dagger(或者如果您愿意,也可以使用 AndroidAnnotations)使将所有内容连接在一起的痛苦减轻一些(并且还可以避免大量 static 实例)。这也使它更容易,例如。 G。有一个组件只处理存储和读取 SharedPreferences 中的登录状态 - 然后这个组件也可以直接连接到您的 ApiService 为所有请求提供会话令牌。

3.) 在内部随意使用 Subject,但在通过调用 return subject.asObservable() 将它们交给 public 之前 "cast" 将它们交给 Observable .这可以防止其他 类 将值推入不应允许的 Subject

Define events

public class Trigger {

public Trigger() {
}

public static class Increment {
}

public static class Decrement {
}

public static class Reset {
}
}

Event controller

public class RxTrigger {

private PublishSubject<Object> mRxTrigger = PublishSubject.create();

public RxTrigger() {
    // required
}

public void send(Object o) {
    mRxTrigger.onNext(o);
}

public Observable<Object> toObservable() {
    return mRxTrigger;
}
// check for available events
public boolean hasObservers() {
    return mRxTrigger.hasObservers();
}
}

Application.class

public class App extends Application {

private RxTrigger rxTrigger;

public App getApp() {
    return (App) getApplicationContext();
}

@Override
public void onCreate() {
    super.onCreate();
    rxTrigger = new RxTrigger();
}


public RxTrigger reactiveTrigger() {
    return rxTrigger;
}


}

Register event listener wherever required

               MyApplication mApp = (App) getApplicationContext();
               mApp
                    .reactiveTrigger() // singleton object of trigger
                    .toObservable()
                    .subscribeOn(Schedulers.io()) // push to io thread
                    .observeOn(AndroidSchedulers.mainThread()) // listen calls on main thread
                    .subscribe(object -> { //receive events here
                        if (object instanceof Trigger.Increment) {
                            fabCounter.setText(String.valueOf(Integer.parseInt(fabCounter.getText().toString()) + 1));
                        } else if (object instanceof Trigger.Decrement) {
                            if (Integer.parseInt(fabCounter.getText().toString()) != 0)
                                fabCounter.setText(String.valueOf(Integer.parseInt(fabCounter.getText().toString()) - 1));
                        } else if (object instanceof Trigger.Reset) {
                            fabCounter.setText("0");
                        }
                    });

Send/Fire event

 MyApplication mApp = (App) getApplicationContext();
 //increment
 mApp
    .reactiveTrigger()
    .send(new Trigger.Increment());

 //decrement
 mApp
    .reactiveTrigger()
    .send(new Trigger.Decrement());

上述库的完整实现,示例 -> RxTrigger