Advertisement
  1. Code
  2. Android SDK

Model View Presenter 在Android 上的测试和依赖注入

by
Read Time:10 minsLanguages:
This post is part of a series called How to Adopt Model View Presenter on Android.
How to Adopt Model View Presenter on Android

Chinese (Simplified) (中文(简体)) translation by Shen Yun Court (you can also view the original English article)

我们在这个序列教程的第一部分探讨了Model View Presenter 的概念, 在第二部分使用我们自己的方式实现了这个模式. 现在是时候更深入一些了. 在这篇教程中, 我们有下面这些内容:

  • 设置测试环境, 为MVP 类编写单元测试
  • 使用依赖注入(Dagger 2) 的方式实现MVP 模式
  • 讨论在Android 使用MVP 应该避免的一些常见问题

1. 单元测试

使用MVP 模式的一个最大的优势就是它简化了单元测试. 所以, 在这个序列教程的最后一部分, 让我们开始为Model 和Presenter 编写单元测试. 我们将使用Robolectric 来允许我们的测试, 这是一个为Android 类提供了很多有用的stub 的测试框架. 为了创建mock 对象, 我们使用Mockito, 它允许我们验证一些方法是否被调用了.

步骤1: 设置

编辑你的APP 模块中的build.gradle 文件, 添加下面的依赖.

在项目的src 文件夹, 创建下面的文件夹test/java/[package-name]/[app-name]. 接下来, 创建一个debug 配置来运行单元测试. 点击上面的Edit Configurations…

Add a ConfigurationAdd a ConfigurationAdd a Configuration

点击 + 按钮然后从列表中选择JUnit.

Select JUnitSelect JUnitSelect JUnit

设置Working directory$MODULE_DIR$.

Configure the ConfigurationConfigure the ConfigurationConfigure the Configuration

我们希望可以使用这个配置来运行所有的单元测试. 设置Test kindAll in package, 然后在Package 字段输入一个包名.

Configure the ConfigurationConfigure the ConfigurationConfigure the Configuration

步骤2: 测试Model

让我们开始为Model 类编写测试. 我们的单元测试使用RobolectricGradleTestRunner.class 来运行, 因为这个类为Android 的特殊操作提供了相应的资源. 需要注意的是, 要使用@Config 注解并提供下面这些选项:

这里直接使用一个实际的DAO(data access object) 来测试数据是不是被正确处理了. 要访问Context 对象, 可以使用RuntimeEnvironment.application 类.

现在是时候去测试Model 的方法了.

你现在可以运行Model 的测试并检查结果. 你也可以自行测试这个类的其他内容.

步骤3: 测试Presenter

现在让我们来测试Presenter. 还是使用Robolectric 来测试, 因为这里使用了一些Android 的类, 例如AsyncTask. 配置和Model 的测试是很相似的. 我们使用View 和Model 的mock 对象来验证方法调用, 并定义方法的返回值.

让我们从clickNewNote() 操作开始测试Presenter 的方法, 这个方法是负责创建一个新的note 并使用AsyncTask 保存到数据库中的.

我们也测试一下当insertNote() 返回错误的场景.

最后, 我们来测试一下deleteNote() 方法, 考虑成功和不成功两种情况.

2. 使用Dagger 2 进行依赖注入

依赖注入对开发者来说是一个很强大的工具. 如果你对依赖注入不熟悉, 那我强烈推荐你看看Kerry 的文章中关于这个的介绍.

依赖注入是一种配置对象的方式, 对象的字段和关联在一个外部的实体进行配置. 换句话说, 对象是在外部实体中进行配置的. 依赖注入是对对象自行配置的一个改变. - Jakob Jenkov

在这个例子里面, 依赖注入允许我们在View 的外面去创建Model 和Presenter, 使得MVP 的分层更加松耦合, 提高了关注点的分离.

我们使用Dagger 2 来处理依赖注入, 这是一个来自Google 的lib. 虽然设置也很直接, 但是dagger 2 也提供了很多很酷的选项, 这是一个相对来说还是比较复杂的库.

我们只专注于这个库和实现MVP 相关的部分. 如果你想要了解更多, 可以看看Kerry 的教程或者是Google 提供的文档.

步骤1: 设置Dagger 2

首先还是要更新项目的build.gradle 来添加依赖.

然后编辑项目的build.dagger 文件.

刷新项目并等待操作完成.

步骤2: 使用Dagger 2 实现MVP

首先为Activity 类创建一个@Scope. 使用scope 的名称创建一个@annotation.

然后, 为MainActivity 创建一个@Module. 如果你有多个activity, 那么你需要为每个Activity 提供各自的@Module.

你还需要创建一个@Subcomponent 来连接我们接下来要创建的应用的@Component.

我们必须为Application 创建一个@Module 和一个@Component.

最后, 我们需要一个Application 类来初始化依赖注入.

不用忘了把这个类添加到项目的manifest 文件.

步骤3: 注入MVP 类

最后, 我们可以@Inject 我们的MVP 类了. 这个注入是在MainActivity 类中进行的. 我们修改Model 和Presenter 的初始化方式. 首先是修改MVP_Main.ProvidedPresenterOps 变量的声明. 它需要是public 的, 并且需要增加@Inject 注解.

添加下面内容以设置MainActivityComponent:

现在我们可以根据StateMaintainer 的状态来初始化或者重新初始化Presenter. 修改setupMVP() 方法, 添加下面内容:

现在, MVP 相关类的初始化就是和View 无关的了. 正因为有了依赖注入, 代码才组织得更好了. 你同样可以使用依赖注入其他的类, 例如DAO, 来更好地改善你的代码.

3. 避免公共问题

我列举了一些在使用MVP 模式的时候应该避免的常见问题.

  • 在访问View 的时候始终检查它是不是可用的. View 是和应用的生命周期绑定的, 很可能在你请求的时候已经被销毁了.
  • 不要忘记在View 被重新创建的时候给Presenter 更新引用.
  • 当View 被销毁的时候, 调用Presenter 的onDestroy(). 有时候还必须在onStop 或者onPause 的时候也通知Presenter.
  • 当View 很复杂的时候, 可以考虑使用多个Presenter.
  • 当使用多个Presenter 的时候, 最简单地在这多个Presenter 传递消息的方法就是使用某种event bus.
  • 考虑使用依赖注入来在View 之外创建Presenter 和Model, 以维持View 层的纯粹.

结论

你已经完成了这个关于MVP 模式的序列教程. 你现在应该可以在你自己的项目中实现MVP 模式了吧, 也应该知道怎么测试它, 甚至使用依赖注入来简化它. 我希望你享受这个过程, 正如我一样. 我希望能再次见到你.

关注我们的公众号
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.