Android 架构选型 (MVP+DataBinding)

经过代码对比,详细讲解MVC,MVP,MVVM之间应该如何选择,以及对Android单元测试的探索。本文的侧重点在于如何选择,并无对每种架构模式概念展开详解(网络上这方面的文章有不少,你们能够自行搜索)。java

大纲

  • MVC or MVP or MVVM?
  • 肯定选型:MVP + DataBinding
  • 单元测试(探索阶段)

目的

  • 提升开发效率
  • 易于测试
  • 拥抱变化
  • 下降维护成本

Android中的MVC

示例:

展现任务详情的功能,详情View层的经过xml来写的,请求数据相关的代码会在Model层提供接口,而后经过Activity对View和Model层进行链接。android

代码:

M:
public interface TaskModel {
    void loadTask(String taskId, OnTaskListener listener);
}

V:
taskdetail.xml:界面布局文件,采用XML进行描述,属于V层的一部分。

C & V:
TaskDetailActivity:C层和V层
public class TaskDetailActivity {
    private void initView() {
        taskModel.loadTask(taskId, new OnTaskListener() {
            public void onSuccess(Task task) {
                //V层代码,可是目前耦合到了C层 
                detailTitle.setText(task.getTitle);
            }
        });
    }  
}复制代码

总结:

  • 编写简单快速,适合含有简单逻辑的业务,或是demo程序。
  • Activity的臃肿:xml做为view层,控制能力太弱,没法动态的改变页面的内容,只能把代码写在activity中,形成了activity既是Controller层,又是View层的问题。
  • 耦合度较高,需求变化改动大,后续维护成本高。
  • Controller混杂着Android代码没法Junit。

Android中的MVP

示例:

展现任务详情的功能,详情View层的经过xml和Activity来完成,请求数据相关的代码会在Model层提供接口,而后经过Presenter对View和Model层进行链接。编程

代码:

M:
public interface TaskModel { 
    void loadTask(String taskId, OnTaskListener listener);
}

V:
taskdetail.xml:界面布局文件,采用XML进行描述,属于V层的一部分。
public class TaskDetailActivity implements TaskDetailView {
    public void showTask(Task task) {
        detailTitle.setText(task.getTitle);
    }  
}

P:
public class TaskDetailPresenter implements Presenter {
    public void getTask() {
        taskModel.loadTask(taskId, new OnTaskListener() {
            public void onSuccess(Task task) {
                //经过接口回调到V层更新UI
                taskDetailView.showTask(task);
            }
        });
    }  
}复制代码

总结:

  • 减小各层之间耦合,易于后续的需求变化,下降维护成本。
  • Presenter层独立于Android代码以外,能够进行Junit测试。
  • 接口和类较多,互相作回调,代码臃肿。
  • Presenter层与View层是经过接口进行交互的,接口粒度很差控制。

Android中的MVVM

示例:

展现任务详情的功能,详情View层的经过xml和Activity来完成,请求数据相关的代码会在Model层提供接口,而后经过ViewModel对View和Model层进行链接。网络

代码:

M:
public interface TaskModel ... void loadTask(String taskId, OnTaskListener listener);
V:
taskdetail.xml:界面布局文件,采用XML进行描述,绑定规则在xml中进行定义。
TaskDetailActivity:Activity主要是初始化和补充的功能。
VM:
TaskDetailViewModel {
        public void getTask() {
              taskModel.loadTask(taskId, new OnTaskListener() {
                    public void onSuccess(Task task) {
                        //经过绑定技术更新UI,作到数据独立于UI
                        taskDeatailViewBinding.setTask(task);
            }
              });
        }  
}复制代码

总结:

  • 和MVP比较像,主要区别在于View和ViewModel / Presenter之间的通讯
  • 相比MVP优点是经过DataBinding技术为VM和V层进行数据绑定,提升开发效率,因为目前绑定技术的局限,V层一些界面的处理仍是须要Activity的辅助。
  • VM层掺杂Android代码没法进行Junit测试。

肯定选型

经过以上对比,选择了MVP+DataBinding,此架构模式基于MVP,并使用DataBinding库来显示数据并绑定View。它并不遵循严格的MVVM或MVP模式,由于它同时使用了ViewModel和Presenter。架构

DataBinding

这是我上篇文章咱们为何要使用DataBinding,里面经过代码的对比,总结说明为何要使用DataBinding的技术,有兴趣的同窗能够阅读一下,在这里我把文章里的一小段总结贴出来:mvc

DataBinding为数据驱动:数据变化后自动更新UI;事件处理:直接找到目标实例处理用户操做的事件。这样咱们就不须要和UI或者控件打交道,只须要在java代码中处理业务逻辑就行了,很是清晰,其他的统一交给binding库去完成。下降了代码耦合度,使得数据独立于UI,对之后程序的变化和维护都有积极的影响。框架

MVP+DataBinding

示例:

展现任务详情的功能,数据和事件绑定与基础MVP代码的对比。mvvm

代码:

//普通MVP 任务详情代码示例:
public void onCreateView(...) {
    detailTitle = (TextView) root.findViewById(R.id.task_detail_title);
    detailComplete = (CheckBox) root.findViewById(R.id.task_detail_complete);
    detailComplete.setOnCheckedChangeListener(
           (cb, isChecked) -> presenter.completeChanged(task, isChecked)
    );
}
@Override
public void showDescription(String title) {
    detailTitle.setText(title);
}
//xml文件省略...

//MVP+DataBinding 任务详情代码示例:
@Override
public void showTask(Task task) {
    viewDataBinding.setTask(task);
}
//能够经过布局文件直接绑定到数据模型的属性(xml文件)
<TextView
    android:id="@+id/task_detail_title"
    android:text="@{task.title}" />
//事件绑定一样能够直接在布局文件中实现(xml文件)
<CheckBox
    android:id="@+id/task_detail_complete"
    android:checked="@{task.completed}"
    android:onCheckedChanged="@{(cb, isChecked) -> presenter.completeChanged(task, isChecked)}" />复制代码

总结:

  • DataBinding库提升了开发效率,使得xml布局文件用于将数据绑定到UI元素,也能够绑定一个action handler(Presenter)处理用户操做的事件,能够观察和设置数据,以便在须要时自动更新(双向绑定)。
  • 须要对View和Presenter两层作测试,增长工做量。
  • 目前Android Studio对Databing的支持不是太好(报错和代码自动生成)

单元测试(探索阶段)

Presenter

不须要Android环境,所以使用Junit测试便可 ide

  • JUnit:Java语言的单元测试框架
  • Mockito:模拟对象的测试框架

View

使用Google建议的Espresso进行UI的测试(须要依赖Android环境)布局

  • AndroidJUnitRunner:Android 且与 JUnit 4 兼容的测试运行器
  • Espresso:功能性 UI 测试框架

问题

就目前实践过程当中,会发现须要为测试写一些额外的方法,不是太舒服。而且写两层测试,工做量变大。还有覆盖率以及维护的问题,一直在探索最佳实践,会在之后的文章里面和你们分享。

本片文章来自于本身的编程实战,写的很差的地方请你们帮忙指正,但愿能帮助你们选到合适本身的架构模式。谢谢阅读。

相关文章
相关标签/搜索