我正在使用新的Mosby MVI库来购买新的演示应用。 在演示者中定义意图时,在附加视图时触发/发出意图时,它会不一致。
例如:让我们在活动中定义非常简单的意图
public Observable<Boolean> intentLoadData(){
return Observable.just(true);
}
演示者将意图绑定到:
@Override
protected void bindIntents() {
Observable<MailListViewState> loadData = intent(ExampleViewContract::intentLoadData).flatMap(interactor::loadData)
.observeOn(AndroidSchedulers.mainThread());
subscribeViewState(loadData, ExampleViewContract::render);
}
这个意图很好用。导航到不同的活动(详细视图)并导航回来时,会调用bindIntents()
重新创建意图。 intentLoadData()
不会发出新项目,MviBasePresenter将使用内部BehaviorSubject提供以前的ViewState。
我的问题是:当我稍微调整Intent(用于重新加载数据)时。当重新连接View时,意图开始发出一个项目。
所以我们将意图改为:
private PublishSubject<Boolean> mReloadDataSubject = PublishSubject.create();
private void reloadData(){
mReloadDataSubject.onNext(true);
}
public Observable<Boolean> intentLoadData(){
return mReloadDataSubject.startWith(true);
}
在导航到新活动并返回时没有。重新附加视图时,意图会发出新项。在我的情况下,这会导致对后端的新APU调用重新加载数据,而不是重用最后一个ViewState。即使从未调用reloadData()
,也会发生这种情况。
此行为感觉非常不一致。在重新附加视图期间触发意图时,如何更好地控制?
更新 对我来说更有意思的是,如何在不完成Observable的情况下避免重新连接时自动发出意图。 随着PublishSubject的引入,即使只是旋转,活动也会重新加载整个数据。
答案 0 :(得分:2)
要回答我自己的问题并结束评论,这是我的解决方案:
首先,我们必须了解Mosby3 MVI如何恢复视图,例如:旋转后,前后导航到不同的视图。
Mosby3保留了演示者的实例。创建视图的新实例时,将恢复演示者并将其附加到视图。新视图的onStart()
,演示者将更新意图。因此,新视图会创建新的意图,演示者将使用PublishSubject
订阅它们。
如果上一个视图的意图发出onComplete()
,PublishSubject
也会完成,并且流关闭。绑定到此意图的(交互器)逻辑将被取消订阅。因此,视图不再能够触发此意图。
在原始问题的例子中。 Observable.just(true)
关闭了流。即使重新创建视图及其意图(旋转后),也不会发出新项目。
mReloadDataSubject.startWith(true)
代替不会发出onComplete()
并且流不是t closed. When the presenter resubscribes to that intent (after rotation), the intent emits the
startsWith(true)`。在该示例中,这导致在每次旋转时完全重新加载数据。
为了触发条件重新加载RxNavi上的意图可能非常有帮助。
public Observable<Boolean> intentReloadData() {
//check if the data needs a reload in onResume()
return RxNavi.observe(this, Event.RESUME)
.filter(ignored -> mNeedsReload == true)
.map(ignored -> true);
}
答案 1 :(得分:1)
Mosby MVI尊重Reactive Streams合同。看看intentLoadData()
public Observable<Boolean> intentLoadData(){
return Observable.just(true);
}
Observable.just(true)
不仅会调用onNext(true)
,还会调用onCompleted()
。完成Reactive流后,不能通过流发出更多项。在onComplete()
之后,可观察流将永久关闭。
在这种情况下使用PublishSubject
完全没问题,但为了更好的可读性,我建议不要使用startWith()
,而是做类似的事情:
public class MyActivity extends MviActivity<MyView, MailListViewState> {
private PublishSubject<Boolean> mReloadDataSubject = PublishSubject.create();
public void onResume(){
super.onResume();
// Triggers on screen orientation changes and
// when navigating back to this screen from back stack
mReloadDataSubject.onNext(true);
}
public Observable<Boolean> intentLoadData(){
return mReloadDataSubject;
}
}
顺便说一下。您还可以使用来自Trello的Navi库,它为生命周期事件提供Observable流,但请记住,如果活动被销毁(即在屏幕方向更改期间),Navi会发出onCompleted()
事件,因此您将结束在相同的情况下:如果您想稍后再次激活意图,则必须确保未调用onCompleted()
。