美文网首页Android开发架构模式高级汇总
从google todo-mvp示例再次学习MVP

从google todo-mvp示例再次学习MVP

作者: Ruheng | 来源:发表于2018-02-28 15:04 被阅读2249次

已经使用了一段时间的MVP模式,今天再以google官方的安卓架构示例todo-mvp为例,再次学习MVP模式。

一、MVP简介

  • Model: 数据层,负责与网络层和数据库层的逻辑交互。
  • View: UI层,显示数据, 并向Presenter报告用户行为。
  • Presenter: 从Model拿数据,应用到UI层,管理UI的状态,响应用户的行为。

二、MVP优势

在学习todo-mvp之前,先了解一下MVP的优势。

  • 分离了视图逻辑和业务逻辑,降低了耦合。
  • Activity只处理生命周期的任务,代码变得更加简洁。
  • 视图逻辑和业务逻辑分别抽象到了View和Presenter的接口中,提高代码的阅读性。
  • Presenter被抽象成接口,可以有多种具体的实现,所以方便进行单元测试。
  • 把业务逻辑抽到Presenter中去,避免后台线程引用着Activity导致Activity的资源无法被系统回收从而引起内存泄露和OOM。

三、todo-mvp结构解析

1.项目结构


从上图可以看出,todo-mvp是按照功能模块划分的。

其中tasks, taskdetail, addedittask, statistics是四个业务模块。

data是数据模块,其中具体的类TasksRepository担任Model层,负责远程和本地数据的获取。

BasePresenterBaseView是presenter 和 view 的基类,在具体模块承担实际功能。最后,util是工具类集合。

2.具体解析

在todoapp中,MVP的具体结构如下图所示:



下面以tasks模块具体阐述上述图片中的实际作用关系。

基类

public interface BasePresenter {

    void start();

}

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

public interface BaseView<T> {

    void setPresenter(T presenter);

}

其中setPresenter()方法作用是在将presenter实例传入view中,其调用时机是presenter实现类的构造函数中

契约类

与之前使用的MVP实现不同,官方的实现中加入了契约类来统一管理view与presenter的所有的接口,这种方式使得view与presenter中有哪些功能,一目了然,维护起来也方便,同时使得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();
    }
}

TasksActivity

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

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

        // 创建 presenter,TasksPresenter是TasksContract.Presenter 的实现类
       // 传入两个参数 
       //1.TasksRepository实例,负责数据层  
       //2.tasksFragment,是TasksContract.View的实现类,即view实例
        mTasksPresenter = new TasksPresenter(
                Injection.provideTasksRepository(getApplicationContext()), tasksFragment);

其中,通过实例化TasksPresenter时,传入tasksFragment,使得在TasksPresenter中拥有view实例。同时,在实例化时初始化构造函数,调用了setPresenter()方法,使得view实例中拥有了presenter实例对象,使得两者联系起来。

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);
    }

TasksFragment

将Fragment作为view层的实现类,使得Activity作为一个全局控制类来创建对象,而Fragment作为view,两者各司其职。同时,Fragment比较灵活,能够方便的处理界面适配的问题。

public class TasksFragment extends Fragment implements TasksContract.View {
    ...........
    public static TasksFragment newInstance() {
        return new TasksFragment();
    }
    ...........
    @Override
    public void onResume() {
        super.onResume();
        mPresenter.start();
    }
    ...........
    @Override
    public void setPresenter(@NonNull TasksContract.Presenter presenter) {
        mPresenter = checkNotNull(presenter);
    }
    ...........
    @Override
    public boolean isActive() {
        return isAdded();
    }
    ...........
}

对于 view 的实现TasksFragment,只挑一部分重要的方法来看。

  • newInstance ()方法,实例化TasksFragment对象。
  • setPresenter()方法继承于父类,通过该方法,view 获得了 presenter 得实例,从而可以调用 presenter 代码来处理业务逻辑。
  • onResume()中,调用了 presenter 得start()方法,获取数据并操作view界面的显示。
  • isActive()方法,通过isAdded()判断对应Activity是否销毁。在Fragment在执行异步耗时操作后,如果调用Activity实例,应当先使用isActive()方法加以判断。

四、总结

通过对todo-mvp分析,再次了解学习了MVP。从google提供的例子中可以看出,MVP的实现较为简单,model、view和presenter各个职责明确,便于扩展维护。contract契约类的出现,使得model和presenter结构更加清晰明了。Activity和Fragment的配合,使得Activity职能更为简化,同时View的实现更加灵活。

相关文章

  • 从google todo-mvp示例再次学习MVP

    已经使用了一段时间的MVP模式,今天再以google官方的安卓架构示例todo-mvp为例,再次学习MVP模式。 ...

  • 跟我一起从Google todo-mvp示例再探MVP

    已经使用了一段时间的MVP模式,今天再以google官方的安卓架构示例todo-mvp为例,再次学习MVP模式。 ...

  • GOOGLE TODO-MVP 学习笔记

    GOOGLE TODO-MVP 学习笔记 背景(可忽略):《GOOGLE TODO-MVP 学习笔记》这篇文章主要...

  • Google官方MVP示例之TODO-MVP

    Google官方MVP示例之TODO-MVP 欢迎转载,转载请注明源地址:http://blog.csdn.net...

  • Google官方android架构todo-mvp(译)

    todo-mvp架构项目地址 todo-mvp 这个app版本被称作todo-mvp,给这个工程的其他示例提供一个...

  • MVP学习

    本文主要学习google开源代码TODO-MVP 地址 https://github.com/googlesamp...

  • Android-Architecture学习篇一:基础的MVP架

    1 前言 作为google官方的安卓架构, 官方地址 ,很有学习的必要! 2 基础的MVP架构 todo-mvp/...

  • todo-mvp

    todo-mvp 当前版本的app叫做 todo-mvp,为该 github 项目中的其他示例提供了一个基础。样本...

  • Android MVP 的浅理解

    虽然多次看了 google 给出 mvp 例子,但是感觉总是理解不了,这次终于看懂了,以官方例子todo-mvp写...

  • Google TODO-MVP详解

    简单介绍 在日常的开发当中,经常会遇到需求的变动。这个东西是真的难以避免的,所以对于产品的基础框架就比较重要了。G...

网友评论

  • 78983551cc90:都用mvvm了你还研究mvp
    只能陪你走一程:这个逼装的好
  • 有点健忘:从骨子里排斥这种咋办啊,我就喜欢写在一个类里,找起来方便,谁告诉我下咋能接受这种模式。得先接受了才能学进去。:grin:
    我也下了demo,下了个kotlin版的,结果看着看着跑去研究kotlin语法了,因为我发现有的语法我看不懂。。。哎,感觉有点像猴子了。。。
    15bb206a4b2a:啊哈哈 昨天跟你一样也是“骨子里排斥”,今天就觉着,这也太他喵好用了,相见恨晚。:joy:
    走在路上的IT男:MVP MVC,都很早就用到公司项目里面了,当然最初就是按照MVC来设计的,我个人觉得,还是要根据经验依照项目的实际来做,不能说mvp比mvc好也不能说mvc就比mvp方便,架构永远是根据项目需求走的。谁合适用谁。
  • JulianAndroid:一直在用这种模式,并且已应用到公司项目和个人项目中。

本文标题:从google todo-mvp示例再次学习MVP

本文链接:https://www.haomeiwen.com/subject/gvjbxftx.html