MVP和数据加载

时间:2018-06-01 15:15:08

标签: java android multithreading android-mvp

我引用的代码来自一个与googlecodelabs/android-testing非常相似的应用。

由于多种原因,我们希望遵循MVP模式,因此我们希望尊重依赖性反转原则,并且永远不要让Presenter了解活动,片段或任何与上下文相关的对象。

与此同时,我们希望View尽可能保持愚蠢,只需将用户交互转发给负责最终更新View的演示者。

因此,经典场景是当用户按下重新加载按钮时,View会将事件转发给演示者,演示者将调用模型以获取新数据并通过某种方式将其传递回View。 .showStuff(stuff)回调。

问题是:你如何处理多线程?该模型将进行网络通话,您不想(甚至不能)在UI线程上执行此操作。

我做了什么,但我不确定它是一个好方法(带来一些丑陋和样板)是让所有事件报告(从View到Presenter的调用)在一个单独的线程上运行(创建每次一个新的主题,这不是一个坏习惯吗?):

@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();
    });
}

我尝试过它并且有效,但我认为我们可以做得更好。有什么建议吗?

3 个答案:

答案 0 :(得分:1)

我建议使用ReactiveX/RxJava这样你就不必处理任何回调。您只需从模型中返回某种Observable,其中包含您的演示者随后订阅的所有数据。使用subscribeOnobserveOn将确保所有工作都在相应的线程中完成。

编辑:

实际上,我错了。您的视图仍会收到来自演示者的回调,但您不必担心它们位于UI主题之外。

答案 1 :(得分:1)

你可以做得更好,但你必须使用其他东西而不是Thread。我认为现在最好的选择是

  1. RxJava2
  2. Kotlin Coroutines(如果你使用kotlin)
  3. 这两种情况都可以让你摆脱可能的回调地狱和召唤runOnUiThread

答案 2 :(得分:1)

您实际上是正确的。有效地实现您所描述的功能确实需要样板(runOnUi)和生成线程(我建议使用缓存线程池执行程序)-通常在模型中。

我对此进行了试验并开发了一种解决方法,该方法在这里写到:Simple MVP for Android,但是样板和恢复视图状态非常痛苦,最终我开发了一个可在此处使用的框架:{ {3}}。

SMVP框架与您在说的非常接近,但是UCS框架可能会让您更感兴趣。它使用注释处理器来自动管理线程并消除尽可能多的样板。它仍在进行中,并不完美,但是您可能会发现它非常有趣。我要补充一点,这两种方法都是为了抵抗旋转而设计的;-)