Android架构选型(MVP+DataBinding)

通过代码对比,详细讲解MVC,MVP,MVVM之间应该如何选择,以及对Android单元测试的探索。本文的侧重点在于如何选择,并没有对每种架构模式概念展开详解(网络上这方面的文章有很多,大家可以自行搜索)。

大纲

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

目的

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

Android中的MVC

示例:

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

代码:

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的技术,有兴趣的同学可以阅读一下,在这里我把文章里的一小段总结贴出来:

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

MVP+DataBinding

示例:

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

代码:

//普通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测试即可

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

View

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

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

问题

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

本片文章来自于自己的编程实战,写的不好的地方请大家帮忙指正,希望能帮助大家选到合适自己的架构模式。
谢谢阅读。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271

推荐阅读更多精彩内容