【发布时间】:2018-02-19 00:14:15
【问题描述】:
我使用 MVP 模式创建了一个应用程序,我找到了这个教程 link 并决定在我的应用程序中实现它,以便片段与它们的活动通信。为了仍然使用 MVP 模式,我将 Eventbus 的实现移至相应的活动展示器和片段展示器。现在我面临一个新问题,我的一个片段需要更改活动参数中的两件事(工具栏相关和 ImageView 可绘制)。我可以在接受函数中以某种方式区分哪个回调来自哪个回调?
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 来包装我的内容(这是框架布局,我将拥有的每个片段都将显示在此容器中)。我这样做的主要原因是在活动和所有片段之间实现单个接口。假设您没有网络连接,我将向用户显示一条消息,让其向下滑动以尝试刷新当前片段。到目前为止,我已经通过将 SwipeRefreshLayout 添加到我拥有的每个片段来完成此操作。它基本上是相同的代码,我想将所有代码合并到活动中的一个位置。我很想使用 EventBus,但据我了解,我需要将所有片段订阅到“事件”onRefresh。 如何将事件发送到适当的片段?
【问题讨论】:
-
这个事件总线实现有点复杂。您可以只拥有一个主题并让它发布。接下来,你的消息对象应该包含两个值,即 int 或 String 事件,T 值。然后在您的订阅者中,您可以在 switch case 中检查事件并相应地转换您的值
-
你能举个例子来说明如何实现它,我还需要发送几个参数,我想发送一个包但我怀疑它是在片段和活动之间发送数据的最佳解决方案
-
现在最好的交互方式是通过数据绑定、视图模型和实时数据。这些功能非常强大developer.android.com/topic/libraries/architecture/… 但是我将提供有关 rxBus 的答案