Android中MVP架构学习及使用(一)

先上一张图MVP的结构图

View:负责绘制UI元素、与用户交互(在Android中体现为Activity)

Model:负责存储、检索、操作数据(有时实现一个Model Interface用来降低耦合)

Presenter:作为View和Model交互的中间纽带,处理与用户交互的逻辑

View Interface:需要View实现的接口,View通过View Interface与Presenter进行交互,降低耦合度,方便单元测试


以下是谷歌官方的mvp项目架构实例,项目地址GitHub:

https://github.com/googlesamples/android-architecture/tree/todo-mvp

基类 Base

BasePresenter 和 BaseView ,这两类分别是所有 Presenter 和 View 的基类。

public interface BasePresenter {

   void start();

}
public interface BaseView<T> {

   void setPresenter(T presenter);

}

BasePresenter 中含有 start() 方法,该方法的作用是 presenter 开始获取数据,并调用 view 中的方法改变界面显示,其调用时机是在 Fragment 类的 onResume 方法中。


@Override
public void onResume() {
   super.onResume();
   mPresenter.start();
}

BaseView 中含有方法 setPresenter ,该方法作用是在将 presenter 实例传入 view 中,其调用时机是 presenter 实现类的构造函数中。


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);
}
契约类 Contract

官方的实现中加入了契约类来统一管理 view 和 presenter 的所有接口,这种方式使得 view 和 presenter 中有哪些功能,一目了然,维护起来也方便,实现如下:


/**
* This specifies the contract between the view and the presenter.
*/
public interface TasksContract {

   interface View extends BaseView<Presenter> {

       void setLoadingIndicator(boolean active);

       void showTasks(List<Task> tasks);
      ...
  }

   interface Presenter extends BasePresenter {

       void result(int requestCode, int resultCode);

       void loadTasks(boolean forceUpdate);

      ...
  }
}

activity 在 mvp 中的作用

activity 在项目中是一个全局的控制者,负责创建 view 以及 presenter 实例,并将二者联系起来,实现如下:


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

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

创建后的 fragment 实例作为 presenter 的构造函数传入,这样就可以在 presenter 中调用 view 中的方法了。

mvp的实现

实例中将fragment作为view层的实现类,为什么是fragment呢?有两个原因,第一个原因是我们把activity作为一个全局控制类来创建对象,把fragment作为view,这样两者就能各司其职。第二个原因是因为fragment比较灵活,能够方便的处理界面适配的问题。我们先看view的实现,我们只挑一部分重要的方法来看

上面可以看到setPresenter方法,该方法继承于父类,通过该方法,view获得了presenter得实例,从而可以调用presenter代码来处理业务逻辑。我们看到在onResume中还调用了presenter得start方法,下面我们再看presenter的实现

presenter 构造函数中调用了 view 的 setPresenter方法将自身实例传入,start 方法中处理了数据加载与展示。如果需要界面做对应的变化,直接调用 view 层的方法即可,这样 view 层与presenter 层就能够很好的被划分。

最后还剩下 model 层实现,项目中 model 层最大的特点是被赋予了数据获取的职责,与我们平常 model 层只定义实体对象截然不同,实例中,数据的获取、存储、数据状态变化都是 model 层的任务,presenter会根据需要调用该层的数据处理逻辑并在需要时将回调传入。这样 model、presenter、view都只处理各自的任务,此种实现确实是单一职责最好的诠释。

 

 

 

 

[参考文章:]
[http://www.jianshu.com/p/8b81493d1297]

[^[Android官方MVP架构示例项目解析](http://www.infoq.com/cn/articles/android-official-mvp-architecture-sample-project-analysis)]:

 

希望这里是一个安静、平和的地方,热爱技术,热爱世界。

感觉自己的人生观、价值观正趋于成熟,系统化,但也许还有很长的路要走。

我们一直在成长的路上。

欢迎关注个人微信公众号:阿拉丁的小站

 

posted @ 2017-09-06 10:51  程序媛小天  阅读(954)  评论(0编辑  收藏  举报