Android 具有interactor和repository的MVP+;rxjava2。在哪里调用observeOn和subscribeOn

Android 具有interactor和repository的MVP+;rxjava2。在哪里调用observeOn和subscribeOn,android,rx-java2,mvp,clean-architecture,Android,Rx Java2,Mvp,Clean Architecture,我有一个基于MVP+交互者+存储库的Android应用程序。从存储库到演示者的所有层都使用反应流(RxJava 2)连接。查看来自演示者的请求、演示者来自交互者的请求、交互者来自存储库的请求以及存储库来自API本身的请求。响应通过与从API到演示者的反应流相同的层。每个层都可以映射底层的数据 问题是。我应该在哪里调用subscribeOn(io()/computation()/etc)和observeOn(AndroidSchedulers.mainThread())? 我认为应该从presen

我有一个基于MVP+交互者+存储库的Android应用程序。从存储库到演示者的所有层都使用反应流(RxJava 2)连接。查看来自演示者的请求、演示者来自交互者的请求、交互者来自存储库的请求以及存储库来自API本身的请求。响应通过与从API到演示者的反应流相同的层。每个层都可以映射底层的数据

问题是。我应该在哪里调用subscribeOn(io()/computation()/etc)和observeOn(AndroidSchedulers.mainThread())? 我认为应该从presenter调用observeOn(AndroidSchedulers.mainThread()),因为在interactor中可能会执行繁重的计算。 在许多示例中,subscribeOn(io()/computation()/etc)是从presenter调用的,但我不同意这种方法。我认为演示者不应该决定在哪个线程中加载数据。存储库应该决定从API加载数据的线程。 例如,如果我们有存储库接口来加载联系人。实现可以从数据库、Internet或内存中获取数据。无需为内存存储库创建线程。所以存储库应该决定是否订阅io/computation/etc调度程序


有什么想法吗?

我不会在存储库层调用
subscribeOn()
observeOn()
,原因如下:

  • 在不同线程上隐式执行的方法很难使用,并且可能会在调用它们的客户端中导致问题
  • 如果您想要组合来自不同存储库的多个流,那么控制它们会更方便。如果它们是在不同的线程上订阅的,这可能会导致细微的错误、低于最佳性能和难以读取的代码
  • 这为回购层增加了另一个职责。repo现在不再是简单的数据存储,而是意识到线程。在我看来,这打破了单一责任原则

我通常在视图之前的最后一层调用
subscribeOn()
observeOn()
,在这种情况下,这将是您的演示者层。在那里,我可以完全控制交互者的组成,更好地判断我想在哪里处理事情,在哪里需要处理结果。

在我的openion中,多线程与模型和逻辑无关。它们可能因平台而异,因此我在表示层中设置了流的调度程序。同意@Malv,它与体系结构无关。通常,我会在视图中进行subscribe,并在presenter中观察api的响应。你能给我举一些例子说明1和2个原因吗?第三个呢,我同意,但我不是舒尔认为演示者应该管理线程。如果我有一个存储库接口的两个实现呢?其中一个只是将数据存储在RAM中。不需要使用单独的线程来写入或读取数据。存储库的另一个实现使用SQLite。所以,当我在presenter中使用subscribeOn时,它应该使用i/o调度程序。我无法预测存储库的哪个实现使用了interactor。这就是为什么我认为存储库应该决定选择哪个调度器。@Radik您是对的,交互者不应该关心repo的具体实现。但是想象一下这个场景——您正在从缓存repo获取数据,并调用
observeOn(AndroidSchedulers.mainThread())
。然后将
flatMap()
发送到另一个执行网络请求的流,最终得到
NetworkOnMainThreadException
。问题不会很明显,也不容易调试。@Radik另外,如果repo的实现发生了变化,会发生什么?线程模型也会在不通知客户端的情况下隐式更改,这可能会导致错误。嗯,最好有一个共同的方法来处理回购方法。从另一个线程调用本地缓存不会导致任何错误,但在错误的线程上发出网络请求可能会导致应用程序崩溃。让开发人员知道哪个方法在哪个线程上工作是不好的。我应该从presenter调用observeOn(AndroidSchedulers.mainThread())。主要的问题是在哪里调用subscribeOn(…)。如果我将缓存的repo流平面映射到执行网络请求的另一个流,那么我不会得到NetworkOnMainThreadException