【问题标题】:MVP and data loadingMVP 和数据加载
【发布时间】:2018-06-01 15:15:07
【问题描述】:

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

出于多种原因,我们希望遵循 MVP 模式,因此我们希望尊重依赖倒置原则,并且永远不要让 Presenter 知道活动、片段或任何与上下文相关的对象。

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

所以一个经典的场景是当用户按下重新加载按钮时,View 将事件转发给 Presenter,Presenter 将调用 Model 以获取新数据并通过某种方式将其传递回 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();
    });
}

我试过了,效果很好,但我认为我们可以做得更好。有什么建议吗?

【问题讨论】:

    标签: java android multithreading android-mvp


    【解决方案1】:

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

    1. RxJava2
    2. Kotlin Coroutines(如果你使用 kotlin)

    这两种情况都使您摆脱了可能的回调地狱和调用 runOnUiThread

    【讨论】:

      【解决方案2】:

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

      编辑:

      其实我说错了。您的视图仍会收到来自您的演示者的回调,但您不必担心它们在 UI 线程之外。

      【讨论】:

      • LiveData 怎么样?但是需要在每次用户请求时触发重新加载,而不是关注远处的数据库。每次用户请求重新加载时,从网络下载文章,然后将它们推送到 UI 已经具有 LiveData(可观察)的本地数据库,这可能是一个好主意。但是本地数据库对于我想要保持简单的东西来说太多了^^
      【解决方案3】:

      其实你说的很对。有效地实现您所描述的确实需要样板文件 (runOnUi) 和生成线程(我建议使用缓存线程池执行器) - 通常在模型中。

      我对此进行了试验并开发了一种方法,我在这里写过:Simple MVP for Android,但样板文件和恢复视图状态证明是如此痛苦,以至于我最终开发了一个我在此处提供的框架:UCS Framework .

      SMVP 框架与您所说的非常接近,但您可能对 UCS 框架更感兴趣。它使用注释处理器来自动管理线程并尽可能多地消除样板。它仍在进行中,并不完美,但您可能会发现它非常有趣。我应该补充一点,这两种方法都是为了在轮换中生存;-)

      【讨论】:

        猜你喜欢
        • 2012-04-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-11
        相关资源
        最近更新 更多