Android架构选型(MVP+DataBinding)

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

 

大纲

 

 

· MVC or MVP or MVVM

 

· 确定选型:MVP + DataBinding

 

· 单元测试(探索阶段)

 

 

目的

 

 

· 提高开发效率

 

· 易于测试

 

· 拥抱变化

 

· 降低维护成本

 

 

Android中的MVC

 

示例:

 

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

 

代码:

 

Mpublic interface TaskModel {

    void loadTask(String taskId, OnTaskListener listener);

}

 

V

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

 

C & V:

TaskDetailActivityC层和Vpublic 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层的通过xmlActivity来完成,请求数据相关的代码会在Model层提供接口,然后通过PresenterViewModel层进行连接。

 

代码:

 

Mpublic 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层的通过xmlActivity来完成,请求数据相关的代码会在Model层提供接口,然后通过ViewModelViewModel层进行连接。

 

代码:

 

Mpublic interface TaskModel  ...

    void loadTask(String taskId, OnTaskListener listener);

V

taskdetail.xml:界面布局文件,采用XML进行描述,绑定规则在xml中进行定义。

TaskDetailActivityActivity主要是初始化和补充的功能。

VM

TaskDetailViewModel {

        public void getTask() {

              taskModel.loadTask(taskId, new OnTaskListener() {

                    public void onSuccess(Task task) {

                        //通过绑定技术更新UI,做到数据独立于UI

                        taskDeatailViewBinding.setTask(task);

            }

              });

        }  

}

 

总结:

 

 

· MVP比较像,主要区别在于ViewViewModel / Presenter之间的通信

 

· 相比MVP优势是通过DataBinding技术为VMV层进行数据绑定,提高开发效率,由于目前绑定技术的局限,V层一些界面的处理还是需要Activity的辅助。

 

· VM层掺杂Android代码无法进行Junit测试。

 

 

确定选型

 

通过以上对比,选择了MVP+DataBinding,此架构模式基于MVP,并使用DataBinding库来显示数据并绑定View。它并不遵循严格的MVVMMVP模式,因为它同时使用了ViewModelPresenter

 

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)

    );

}@Overridepublic void showDescription(String title) {

    detailTitle.setText(title);

}//xml文件省略...

//MVP+DataBinding   任务详情代码示例:@Overridepublic 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 handlerPresenter)处理用户操作的事件,可以观察和设置数据,以便在需要时自动更新(双向绑定)。

 

· 需要对ViewPresenter两层做测试,增加工作量。

 

· 目前Android StudioDatabing的支持不是太好(报错和代码自动生成)

 

 

单元测试(探索阶段)

 

Presenter

 

不需要Android环境,因此使用Junit测试即可

 

 

· JUnitJava语言的单元测试框架

 

· Mockito:模拟对象的测试框架

 

 

View

 

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

 

 

· AndroidJUnitRunnerAndroid 且与 JUnit 4 兼容的测试运行器

 

· Espresso:功能性 UI 测试框架

 

 

问题

 

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

 

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

谢谢阅读。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值