您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center   Code  
会员   
   
 
     
   
 订阅
  捐助
Android DataBinding原理解析
 
来源:csdn 发布于: 2017-6-5
  6830  次浏览      17
 

一、简介

首先声明,本文讲解的Android DataBinding原理,不涉及Android DataBinding的配置和使用,如果大家想了解Android DataBinding的使用教程,请去Google Android官网,里面有非常详细的讲解。另外,本文也不是为Android DataBinding歌功颂德的,如果对着对本文的一些总结有不同观点,请留言,希望和大家一起思考这项“新技术”。

DataBinding框架是去年谷歌 I/O大会上介绍的“新技术”, 数据绑定框架能够给我们带来了一定的方便,无需findviewByID操作也可获取View,数据Model更新自动映射到控件上…… Android Databingding属于单向绑定框架。

顾名思义,DataBinding即数据绑定,数据绑定本不是什么新鲜技术,做asp.NET Web开发的同学应该都用过Databinding绑定图表数据,C#本身也支持控件的数据绑定。在Android层面,Google也不是第一个做数据绑定的,开源项目RoboAndroid早已基于Android平台开发了一套数据绑定框架,RoboAndroid属于双向绑定框架。

单向绑定是指presentation model上的属性更新会自动的同步到相应的视图属性上。双向绑定在单向绑定的基础上,增加了将视图上的变更同步回presentation model相应的属性上。

二、为什么要有Databinding

这要从软件的视图逻辑架构模型说起,常见的模型有MVC、MVP和MVVM,这三种模型各有优缺点,看着很像,其实有较大不同,Android Databinding的作用就是将原来Android开发模式从MVC转到MVVM。Android的Activity+Layout文件模式属于MVC,我们做Android开发的时候会发现,一不小心一个Activity的代码就超过1千多行,视图逻辑和业务逻辑全部混在一起,代码的可维护性非常差,这是Google推出Databinding想解决的问题。

这里复制粘贴一下大牛们对这三个逻辑架构的理解。

1、MVC

MVC,顾名思义,MVC是将Model, View 和Controller分离,让彼此的职责(responsibility)能够明确的分开,这样不论是改M、 V还是C,都可以确保另外两层可不用做任何修改,同时这样的分层也可以加强程式的可测试性(testability),View和Model基本上是相关的,但它们并不会有直接的相依关系,而是由Controller去决定Model产生的资料,然后丢给View去做呈现,也就是说,Controller是Model和View之间的协调者(coordinator),View和Model不能直接沟通,以确保责任的分离。而Controller可以只是一个系结Model和View的小类别,也可以是大到包含Workflow, Enterprise Services或是做为外部系统的Proxy Services等的逻辑系统,MVC各元件是可以分离的组件,也可以是分离的系统(当然要设计一些机制在相互沟通)。可以看到MVC中Controller(Activity)中既要控制视图(Layout)也要处理业务(数据),Controller只是将View(layout)与Model尽可能分开,当然View也可以直接获取Model数据,如果将View与Model完全分开,就要使用MVP框架。

总结MVC:

1) 视图层(View):一般采用XML布局文件进行界面的描述,也可使用代码。

2) 控制层(Controller):Android的控制层是Activity或Fragment,一个Activity可以对应多个Fragment。目前点评Android的框架采用Fragment,大多数页面采用Fragment作为控制层。

3) 模型层(Model):数据模型,由于Android变量个数限制,目前点评Android几乎不存在Model。

缺点:

主要的缺点是Controller太复杂,显示逻辑和其他逻辑混合在一起不好维护;由于缺少数据模型支持,代码更混乱;模块、控件可复用性低。

2、MVP

MVP,MVP一样也是职责分明,且Model与View分离的架构,但是这个P (Presenter)和ViewModel就很类似,不过就如同Presenter (主持人)这个字所代表的意义,所有主控View呈现的工作,都是由Presenter来做,而View本身只是Presenter所要使用的舞台而已,所以View原则上会相依于Presenter,但是为了要做到关注点分离(SoC原则),所以在View和Presenter间都会加入一个介面(ex: IView),然后以IoC的方式将View注射到Presenter中,而Presenter就使用介面所定义的方法去操控,而View就透过介面所定义的方法去呈现介面即可。但也因为受限于介面,所以Presenter只能依介面定义的动作去回应与处理,而不能再做更多的延伸功能,除非更改View的介面。

3、MVVM

MVVM,MVVM的架构一样是M, V分离,但中间是以VM (ViewModel)来串接,这个ViewModel比较像是View的一个代理程式,它负责直接对Model做沟通,而View可以透过一些机制(ex: Events, Two-way Databindings, …)来和ViewModel沟通以取得资料或将资料抛给Model做存取等工作,ViewModel也可以作为和外部系统的代理程式,例如Web Service或是REST Service或是Enterprise Services等等,不过它和MVC不同的地方,就是ViewModel和View的黏合度比较高,因为View必须要透过ViewModel才可以取得Model,而ViewModel又必须要处理来自View的通知讯息,所以虽然职责一样分明,但是却不像MVC那样可以扩展到整个系统元件都能用。如果MVVM要和MVP比较的话,MVVM会比MVP更灵活一点。

 

总结MVVM:

1)低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的”View”上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。

2) 可重用性。你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。

3) 独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用Expression Blend可以很容易设计界面并生成xaml代码。

4)可测试。界面素来是比较难于测试的,而现在测试可以针对ViewModel来写。

由上面各个架构的讨论,我们可以得到以下的结果:

4、总结三种架构:

MVC 架构适合于大型系统,它可以分层且可以在实体层面切割为不同的机器或服务,只要彼此间具有适当的通讯协定即可。

MVVM 架构适合像XAML 这种与程式码无关(code ignorance) 的使用者介面设计,只要View 中下特定的指令与ViewModel 串接,就可以享有ViewModel 沟通的功能,而ViewModel 只需做一些特别的介面实作,即可平顺的和View 沟通。

MVP 架构适合集中由程式码决定View 动作的应用程式,而View 只需要实作特定的介面即可,不需要太复杂的工作,但Presenter 则可能会受限于View 介面的动作,而无法做更进一步对View 的控制。

5、小结

在Android开发中原有的MVC(Activity+layout)模式越来越不适用,首先,视图逻辑和业务逻辑不分,导致代码容易出问题、难以可持续性维护;其次,由于业务逻辑混在视图逻辑里面,视图基本无法复用,layout本身是代码文件,但是又不像Java代码那样可维护,灵活,可以有逻辑,所以很少复用layout文件,有经验的Android程序员会尽可能避免复用Layout文件特别是复用别人写的layout文件。所以出于视图复用的目的原有的MVC也不适用,MVVM成了一种必要的选择。

6、强调

本文需要说明的是Android Databinding只是在Android平台实现MVVM的一种方式,前面说的RoboAndroid也可以实现;或者开发者自己定义一套开发规范和框架,能够将Android开发大道视图、逻辑业务分离,并实现视图高度可复用也是一样的;RxJava也为开发者提供了MVVM的能力。

(1)RoboBinding?

RoboBinding是一款基于Android的数据绑定组件,支持双向绑定等,比较成熟,和DataBinding 类似,因为DataBinding借鉴了RoboBinding,目前DataBinding只支持单向绑定。

与DataBinding相比较, RoboBinding更为成熟,并且支持双向绑定,但是因为DataBinding是Google亲儿子,以后肯定会不断改进,会成为Android新特性,所以采用DataBinding可能更现实,但是我本人并不排斥RoboBinding,通过体验RoboBinding也很不错,侵入性并不是很强

(2)RxJava/ RxAndroid ?

RxJava最核心的两个东西是Observables(被观察者,事件源)和Subscribers(观察者)。Observables发出一系列事件,Subscribers处理这些事件。这里的事件可以是任何你感兴趣的东西(触摸事件,web接口调用返回的数据…);一个Observable可以发出零个或者多个事件,知道结束或者出错。每发出一个事件,就会调用它的Subscriber的onNext方法,最后调用Subscriber.onNext()或者Subscriber.onError()结束。

RxJava更为灵活,但是观察、订阅需要在代码中自己实现,侵入性比较强,也影响代码可读性,就目前代码来看,改造起来代价非常大。在Android项目中很少使用RxJava,虽然功能很强大,将逻辑看做数据流,一切数据驱动,但是代码侵入性太强,不适合在业务逻辑、视图逻辑中大范围使用。但是,RxJava在数据流控制中确实精妙!可以将RxJava包装到你的框架中,负责同一个Activity模块间的数据流控制,用他实现数据数据共享、消息通信,以数据驱动,将其封装到框架中,会是很好的选择。

三、Android DataBinding分析

View —— Layout文件:

手动在Layout文件中使用Model数据为控件赋值。

ViewModel —— ViewDataBinding 实现类

DataBinding框架会根据Layout进行的数据绑定情况自动生成该文件!不可改。 ViewDataBinding负责将Model的数据和更新信息赋值给Layout中的控件,达到单向绑定效果。

Model —— 实现Observable、 ObservableMap或ObservableList接口

负责数据逻辑处理,按照规定的标准写get、set方法,并通知数据更新。框架会在Model内部存储ViewDataBinding ,当Model需要更新数据时,可以通知ViewDataBinding 实现对View更新。

1、例子代码

(1)Model

public class OrderListItemModel extends BaseObservable{ //model继承BaseObservable类
private boolean checked; //定义属性?private int checkBoxVisibility; //定义属性

@Bindable //注解,支持自动更新
public boolean getChecked() {? return checked;? }??@Bindable?public void setChecked(boolean checked) {? this.checked = checked;
//通知OrderListItemModel 中的ViewDataBinding,更新checked属性? notifyPropertyChanged(BR.checked);
}

(2)Layout(View)

声明变量
<layout? xmlns:android= s“http://schemas.android.com/apk/res/android”? xmlns:dp=“http://schemas.android.com/apk/res-auto”? >? <data>? <variable? name=“itemMode”? type= “com.dianping.tuan.ViewModel.OrderListItemModel”>? </variable>? </data>
绑定数据
<CheckBox? android:id= “@+id/check” ? android:layout_width=“wrap_content”? android:layout_height= “wrap_content” ? android:layout_gravity=“center_vertical”? android:button =“@drawable/rad_bg” ? android:checked= “@{itemMode.checked}” //绑定checked ? android:visibility= "@{itemMode.checkBoxVisibility}“ //绑定Visibility? android:clickable= "false"? android:paddingRight =" 10dp " />

(3)ViewModel (桥梁)—— ViewDataBinding

ViewDataBinding文件是框架根据layout文件和model自动生成的,无法修改。TuanOrderCommonItem2Binding类就是框架自动生成的ViewModel,父类是ViewDataBinding(抽象类),是在ViewDataBinding类中完成绑定。
public class TuanOrderCommonItem2Binding extends android.databinding.ViewDataBinding {
this.check = (android.widget.CheckBox) bindings[1];//存储Layout中的控件
private com.dianping.tuan.Model.OrderListItemModel mItemMode; //存储Model数据
// read checked~.~ itemMode ~
if ( itemMode != null)
{
checkedItemMode = itemMode.isChecked(); //获取ItemMode中的数据
}
if ((dirtyFlags & 0b11L) != 0)
{
this.check.setChecked(checkedItemViewMode); //将数据赋值给控件
}
……………………

2、Model如何通知ViewDataBinding更新View?

框架通过观察者模式,异步更新界面!我们看到过程非常复杂,最关键,数据更新的过程是异步的,这可以避免ANR,但是效率呢?如果是数据量比较大的列表或者比较重的主界面,使用数据绑定合适吗?

四、Android Databing总结

本文不是来为Android Databing歌功颂德的,如何使用一项新技术需要智慧,在我们未完全了解它时,最好谨慎的在工程项目中使用。最后罗列一些自己对Android Databing的总结,其中可能有不完善或不成熟的地方,希望大牛们批评指正。如果读者想在自己开发的APP中使用Android Databing,希望你对它优缺点有足够的了解,有充足的思想准备。

优点:

1、自动化绑定+MVVM优点

2、使用DataBinding后,无需直接获取、操作视图元素,能够帮助 Activity或Fragment减少对视图控制的代码量

不足:

1、目前只支持单向绑定;

2、ViewModel与View一一对应;

3、使用起来灵活性比较低;

4、Model属性发生变化时,ViewDatabinding采用异步更新数据,对于现实大量数据的ListView,会有一定延迟,在实践测试中发现,Databing效率较低,对于负责的界面不太适用;

5、自动生成大量代码和属性字段:ViewDataBinding 实现类 DataBinderMapper 等

   
6830 次浏览       17
相关文章

深度解析:清理烂代码
如何编写出拥抱变化的代码
重构-使代码更简洁优美
团队项目开发"编码规范"系列文章
相关文档

重构-改善既有代码的设计
软件重构v2
代码整洁之道
高质量编程规范
相关课程

基于HTML5客户端、Web端的应用开发
HTML 5+CSS 开发
嵌入式C高质量编程
C++高级编程