转载

Android Architecture Blueprints 学习之 TODO-MVP(一)

TODO-MVP 是 Android Architecture Blueprints 中讲解的第一种架构,是一个基本的 MVP 架构。

TasksActivity

APP 的入口是 TasksActivity。

它主要包含有两个成员:

  • TasksFragment:待做清单的主界面( V
  • TasksPresenter:对应的 Presenter( P
  • TasksRepository: 数据源( M

MVP 是如何建立起关系来的?

首先,M 只在 P 中使用,与 V 无关,因此 M 只要传入 P 中即可。

P 与 V 之间的关系是这样的:V 和 P 互相保存对方的实例。V 在需要进行数据操作逻辑的时候不自己做,而是交给 P 来做,P 完成之后调用 V 中的方法实现界面更新。

来看对应的代码如下:

首先创建 TasksFragment,并将 Fragment 添加到 Activity 中:

TasksFragment tasksFragment =         (TasksFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame); if (tasksFragment == null) {     // Create the fragment     tasksFragment = TasksFragment.newInstance();     ActivityUtils.addFragmentToActivity(             getSupportFragmentManager(), tasksFragment, R.id.contentFrame); } 

这里用到一个工具类 ActivityUtils 的函数 addFragmentToActivity,实现为:

public static void addFragmentToActivity (@NonNull FragmentManager fragmentManager,                                           @NonNull Fragment fragment, int frameId) {     checkNotNull(fragmentManager);     checkNotNull(fragment);     FragmentTransaction transaction = fragmentManager.beginTransaction();     transaction.add(frameId, fragment);     transaction.commit(); } 

这里插一句与主题无关的话,一个创建 Fragment,Google 写得如此严谨,还有向 checkNotNull 这种第一次见到函数,我还是得学习一个啊。

创建 M 和创建 P 是在一句话里完成的:

// Create the presenter mTasksPresenter = new TasksPresenter(         Injection.provideTasksRepository(getApplicationContext()), tasksFragment); 

其中:

Injection.provideTasksRepository(getApplicationContext()) 

这一句就创建了 M 数据源,这里用到了依赖注入,这里的依赖不是靠框架完成的,手动指定的。这里就不展开了,总之这句返回一个 TasksRepository 实例。

P 和 V 相互保存对方的实例发生在 TasksPresenter 的构造函数当中:

public TasksPresenter(@NonNull TasksRepository tasksRepository, @NonNull TasksContract.View tasksView) {     mTasksRepository = checkNotNull(tasksRepository, "tasksRepository cannot be null");     mTasksView = checkNotNull(tasksView, "tasksView cannot be null!");      mTasksView.setPresenter(this); } 

第一句是将 M 存进 P,第二句是将 V 存进 P,第三句是将 P 存进 V。

TasksActivity V 与 P 的功能划分

在不使用 MVP 的传统结构当中,Activity / Fragment 除了界面的显示逻辑之外,往往还需要实现判断逻辑、数据加载逻辑,就导致结构非常复杂,不好维护。

在 MVP 结构当中,V 中只保留与界面显示有关的逻辑,将判断逻辑和数据加载等都移到 P 中去,这样就实现了一个拆分,使得结构变清晰,因此可维护性就提高了。

对于 TasksActivity 这个 TODO list 应用的主界面而言,V 和 P 具体应该如何划分呢?

下图是 TasksActivity 的界面:

Android Architecture Blueprints 学习之 TODO-MVP(一)

从界面中,我们可以看出 TasksActivity 具备以下功能:

  • 点击添加 FAB 进入 AddEditTaskActivity 添加页面
  • 点击 TODO item 进入详情页
  • 点击 TODO item 的勾设为已完成
  • 下拉刷新
  • 过滤菜单:所有、活动状态、已完成
  • 菜单:清除已完成、刷新
  • 添加完成弹出 SnackBar 提示成功
  • 生命周期:onResume、onActivityResult

对于界面上的这些功能,需要进一步拆分,将数据有关的放入 P,将显示有关的留在 V,还有一点要强调的是, P 需要绑定生命周期,即在 P 中创建同名方法,在 V 的生命周期中调用,这样保证 P 中的数据源响应生命周期,能及时更新状态

V、P 的接口

上一节中总结了 TasksActivity 的功能,并思考如何将功能分别拆放到 V、P 中。

TasksContract 接口中就存放了拆分的结果,它包含两个接口 View 和 Presenter,其内容如下:

public interface TasksContract {      interface View extends BaseView<Presenter> {         void setLoadingIndicator(boolean active);         void showTasks(List<Task> tasks);         void showAddTask();         void showTaskDetailsUi(String taskId);         void showTaskMarkedComplete();         void showTaskMarkedActive();         void showCompletedTasksCleared();         void showLoadingTasksError();         void showNoTasks();         void showActiveFilterLabel();         void showCompletedFilterLabel();         void showAllFilterLabel();         void showNoActiveTasks();         void showNoCompletedTasks();         void showSuccessfullySavedMessage();         boolean isActive();         void showFilteringPopUpMenu();     }      interface Presenter extends BasePresenter {         void result(int requestCode, int resultCode);         void loadTasks(boolean forceUpdate);         void addNewTask();         void openTaskDetails(@NonNull Task requestedTask);         void completeTask(@NonNull Task completedTask);         void activateTask(@NonNull Task activeTask);         void clearCompletedTasks();         void setFiltering(TasksFilterType requestType);         TasksFilterType getFiltering();     } } 

这个接口是 MVP 概念中很重要的一个部分。它相当于对一个页面显示、加载数据的一个大纲。在实际的开发过程中,设计好一个界面的原型后,就应该来构思这个接口,思考这个界面都要现实哪些东西,要加载哪些数据,如何进行拆分,先把这个接口写出来。

有了这个接口之后,TasksFragment 实现TasksContract.View,TasksPresenter 实现 TasksContract.Presenter。有一点要注意的是,V 和 P 是紧密耦合在一起的,两者之间会经常相互调用。

至此,本文从 TasksActivity 的代码入手,主要分析了 MVP 中 V 与 P 的关系。在后续的文章中,我会继续对 TODO-MVP 这个官方的 MVP 示范项目进行分析。

原文  http://www.judymax.com/archives/1141
正文到此结束
Loading...