4

为了使用 mvp 模式在 android 上实现“干净”架构,建议将 android 框架视为插件,并且不要将任何 android 感知依赖项泄漏到 Presenter 层。使用 rxjava,如果我有一个设计为将数据“推送”到视图层的演示器,我可能想要这样的逻辑:

public interface SearchPresenter {

  interface ViewLayer {
  void updateResults(List<SearchResult> searchResults)
  }
  void bind(ViewLayer viewLayer);
  void unbind();
}

public class SearchPresenterImpl implements SearchPresenter {

   ViewLayer viewLayer;
   CompositeDisposable compositeDisposable;

    @Override
    public void bind(ViewLayer viewLayer) {
      this.viewLayer = viewLayer;

      compositeDisposable = new CompositeDisposable();
      compositeDisposable.add(
            searchInteractor.getSearchResults()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(this::refreshView));

}

private void refreshView(List<SearchResult> searchResults) {
    //send the results back to the view layer to update a RecyclerView      
    viewLayer.updateResults(searchResults)
}

@Override
public void unbind() {
    compositeDisposable.dispose();
}

但是,通过观察“AndroidSchedulers.mainThread()”,这会强制依赖:

import io.reactivex.android.schedulers.AndroidSchedulers

在这一点上,我的演示者现在知道了 android 并与之绑定;我想避免。

处理此问题的建议方法是什么,以便保证将结果传递到 android 的 UI(主)线程上的 ViewLayer,而演示者不依赖于任何与 android 相关的东西?

4

2 回答 2

8

AndroidSchedulers.mainThread()使用 Android 代码在主线程上安排操作,不要直接在演示者中使用它。相反,您可以重构演示者以在其构造函数中使用调度程序,在生产代码中使用常规AndroidSchedulers.mainThread()and Schedulers.io(),在测试中您可以发送Schedulers.trampoline()or Schedulers.immediate()

在此示例中查看此模式:https ://github.com/riggaroo/GithubUsersSearchApp/blob/master/app/src/main/java/za/co/riggaroo/gus/presentation/search/UserSearchPresenter.java

及其测试类在这里: https ://github.com/riggaroo/GithubUsersSearchApp/blob/8b83095d7a2cc8f3cb69a945224ab4c37cf54a37/app/src/test/java/za/co/riggaroo/gus/presentation/search/UserSearchPresenterTest.java

于 2017-10-04T17:54:44.147 回答
2

正如前面的答案所指出的,您可以注入Scheduler构造函数,Presenter但至少还有两种可能性。

  1. Scheduler您可以直接注入interactor,然后您不需要在presenter. 然后在测试中你可以模拟你的interactor并完全忘记rxjava测试中的依赖。

  2. 如果您觉得保留在交互器中很好,您可以在测试中使用RxJavaPlugins和覆盖调度程序。RxAndroidPluginsAndroidSchedulers

所以定义(Kotlin):

object RxJavaPluginHelper {

    fun setup(scheduler: Scheduler = Schedulers.trampoline()) {
        RxAndroidPlugins.setInitMainThreadSchedulerHandler { _ -> scheduler }
        RxJavaPlugins.setComputationSchedulerHandler { scheduler }
        RxJavaPlugins.setIoSchedulerHandler { scheduler }
        RxJavaPlugins.setNewThreadSchedulerHandler { scheduler }
        RxJavaPlugins.setSingleSchedulerHandler { scheduler }
    }

    fun teardown() {
        RxAndroidPlugins.reset()
        RxJavaPlugins.reset()
    }
}

然后使用

 companion object {
        @BeforeClass
        @JvmStatic
        fun setup() {
            RxJavaPluginHelper.setup()
        }

        @AfterClass
        @JvmStatic
        fun teardown() {
            RxJavaPluginHelper.teardown()
        }
    }

就我个人而言,我不会为从演示者中删除这条线而战,因为删除Android导入背后的整个想法Presenter是使其可移植到不同的平台,但由于不太可能发生,我会认为它没问题。

于 2017-10-05T06:29:57.633 回答