我要引用的代码来自一个与googlecodelabs/android-testing非常相似的应用程序。
由于许多原因,我们希望遵循MVP模式,因此我们希望尊重依赖反转原则,并且永远不会让展示者知道活动、片段或任何与上下文相关的对象。
同时,我们希望视图尽可能地保持哑巴,只将用户交互转发给最终负责更新视图的演示者。
因此,一个经典的场景是,当用户按下重新加载按钮时,视图将事件转发给演示者,演示者将调用模型以获取新数据,并通过某种.showStuff(stuff)回调将其传递回视图。
问题是:在这种情况下,如何处理多线程?该模型将发出网络调用,而您不希望(甚至不能)在UI线程上执行此操作。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_articles);
mPresenter = new ArticlesPresenter(this, Injector.provideArticlesRepository());
new Thread(() -> {
mPresenter.loadArticles(true);
}).start();
}
@Override
public void onClick(View v) {
new Thread(() -> {
mPresenter.loadArticle(articleId);
}).start();
}由于Presenter的回调现在将来自非UI线程,因此我们需要确保所有UI更新都在UI线程上运行:
@Override
public void setProgressIndicator(boolean active) {
runOnUiThread(() -> {
Log.i(TAG, "set progress indicator : "+active);
Toast.makeText(this, "progress indicator: "+active, Toast.LENGTH_SHORT).show();
});
}
@Override
public void showArticles(Map<String, List<Article>> articles) {
runOnUiThread(() -> {
Log.i(TAG, "show articles, keys: " + articles.keySet());
Toast.makeText(this, "show all articles", Toast.LENGTH_SHORT).show();
});
}我试过了,它起作用了,但我认为我们可以做得更好。有什么建议吗?
发布于 2018-06-01 23:37:45
您可以做得更好,但您必须使用其他东西,而不是Thread。我认为现在最好的选择是
RxJava2Coroutines (如果使用kotlin)这两种情况都使您避免了可能的回调地狱和调用runOnUiThread
发布于 2018-07-07 15:20:09
你实际上是非常正确的。要有效地实现您所描述的内容,确实需要样板(runOnUi)和派生线程(我建议使用缓存线程池执行器)--通常在模型中。
我在这里尝试并开发了一种方法:Simple MVP for Android,但样板和恢复视图状态被证明是如此痛苦,以至于我最终开发了一个框架,我在这里提供了这个框架:UCS Framework。
SMVP框架与您所说的非常接近,但您可能对UCS框架更感兴趣。它使用注释处理器自动管理线程,并尽可能多地消除样板。它仍在发展中,并不完美,但您可能会发现它非常有趣。我应该补充说,这两种方法都是为了在轮换中幸存下来而设计的;-)
https://stackoverflow.com/questions/50646513
复制相似问题