区分同一Eventbus上的多个事件

时间:2018-02-19 00:14:15

标签: android mvp event-bus

我使用MVP模式创建了一个应用程序,我找到了这个教程link,并决定在我的应用程序中实现它,以便片段与他们的活动进行通信。我将Eventbus的实现移动到对应的活动演示者和片段演示者,以便仍然使用MVP模式。现在我面临一个新问题,我的一个片段需要在活动参数中更改两件事(工具栏相关和ImageView drawable)。我可以在接受函数中以某种方式区分回调吗?

RxBus类

public final class RxBus {

    private static SparseArray<PublishSubject<Object>> sSubjectMap = new SparseArray<>();
    private static Map<Object, CompositeDisposable> sSubscriptionsMap = new HashMap<>();

    public static final int CHANGE_APP_BAR_LAYOUT = 0;
    public static final int CHANGE_POSTER_IMAGE = 1;

    @IntDef({CHANGE_APP_BAR_LAYOUT, CHANGE_POSTER_IMAGE})
    @interface Subject {
    }

    private RxBus() {
        // hidden constructor
    }

    /**
     * Get the subject or create it if it's not already in memory.
     */
    @NonNull
    private static PublishSubject<Object> getSubject(@Subject int subjectCode) {
        PublishSubject<Object> subject = sSubjectMap.get(subjectCode);
        if (subject == null) {
            subject = PublishSubject.create();
            subject.subscribeOn(AndroidSchedulers.mainThread());
            sSubjectMap.put(subjectCode, subject);
        }

        return subject;
    }

    /**
     * Get the CompositeDisposable or create it if it's not already in memory.
     */
    @NonNull
    private static CompositeDisposable getCompositeDisposable(@NonNull Object object) {
        CompositeDisposable compositeDisposable = sSubscriptionsMap.get(object);
        if (compositeDisposable == null) {
            compositeDisposable = new CompositeDisposable();
            sSubscriptionsMap.put(object, compositeDisposable);
        }

        return compositeDisposable;
    }

    /**
     * Subscribe to the specified subject and listen for updates on that subject. Pass in an object to associate
     * your registration with, so that you can unsubscribe later.
     * <br/><br/>
     * <b>Note:</b> Make sure to call {@link RxBus#unregister(Object)} to avoid memory leaks.
     */
    public static void subscribe(@Subject int subject, @NonNull Object lifecycle, @NonNull Consumer<Object> action) {
        Disposable disposable = getSubject(subject).subscribe(action);
        getCompositeDisposable(lifecycle).add(disposable);
    }

    /**
     * Unregisters this object from the bus, removing all subscriptions.
     * This should be called when the object is going to go out of memory.
     */
    public static void unSubscribe(@NonNull Object lifecycle) {
        //We have to remove the composition from the map, because once you dispose it can't be used anymore
        CompositeDisposable compositeDisposable = sSubscriptionsMap.remove(lifecycle);
        if (compositeDisposable != null) {
            compositeDisposable.dispose();
        }
    }

    /**
     * Publish an object to the specified subject for all subscribers of that subject.
     */
    public static void publish(@Subject int subject, @NonNull Object message) {
        getSubject(subject).onNext(message);
    }
}

MainPresenter类

public class MainPresenter extends BasePresenter<MainView> implements Observer<ConfigurationResponse>,Consumer<Object>
{
     ...
     @Override
     public void accept(Object o) throws Exception {
          //here is the problem how can I know if I should call to changeAppBar or change Image url?
     }

ClientPresenter类

public class ClientPresenter extends BasePresenter<SeriesSpecsView>
{
    ...

    //I'm calling to those function withing the fragment when the user click on the ui
    public void setPosterUrl(String posterUrl)
    {
        RxBus.publish(RxBus.CHANGE_POSTER_IMAGE,posterUrl);
    }

    public void setAppBarLayoutParams(boolean collapse)
    {
        RxBus.publish(RxBus.CHANGE_APP_BAR_LAYOUT,collapse);
    }
}

我找到了解决这个问题的两个解决方案:

1)通过调用instanceof函数来检查对象,不是很有效,如果我需要在两个事件之间发送相同类型的信息?

2)添加另一个evenbus,但我不认为为你想要回调活动的每个事件都有单独的eventbus是合乎逻辑的。

感谢您的帮助

更新

我遇到了另一个问题(或者至少是潜在的问题)。我添加了一个SwipeRefreshLayout来包装我的内容(这是framelayout,我将拥有的每个片段都将显示在此容器中)。我这样做的主要原因是在活动和所有片段之间实现单一界面。假设您没有网络连接我会向用户显示一条消息,向下滑动以尝试刷新当前片段。到目前为止,我已经通过将SwipeRefreshLayout添加到我拥有的每个片段来完成此操作。它基本上是相同的代码,我想将所有代码合并到活动中的一个位置。我很想使用EventBus,但据我所知,我需要将所有片段订阅到“事件”onRefresh。 如何将事件发送到适当的片段?

1 个答案:

答案 0 :(得分:0)

我使用RxBus传输全局事件。您也可以按照自己的方式使用它。

class RxBus {
    private val  busSubject: Subject<ActionEvent<out Any>> =
            PublishSubject.create()

    fun  register( onNext:
    Consumer<ActionEvent<out Any>>):Disposable{
        return busSubject
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(onNext)

    }


    fun post(event: ActionEvent<out Any>) {
        busSubject.onNext(event)
    }

}

open class ActionEvent<T>(val action: ActionEnum
                     , val event: T) {


}

您可以使用String代替ActionEnum,它只是一个枚举类

当你发布内容时,

getRxBus()?.post(ActionEvent(ActionEnum.CHANGE_APP_BAR_LAYOUT,collapse))

如果您想订阅,

val disposable = rxBus.subscribe(Consumer{...})

请记得将销售处置废弃。