DataBinding是谷歌官方发布的一个框架,基于页面数据直接绑定的mvvm框架,最初接触其时被惊艳到了,其可以在xml文件直接绑定数据,通过Binding类直接拿到有id的控件,页面对数据的监听可以直接修改数据就能改变页面的数据,即使页面有多处使用到。但我现在决定弃用他了。下面一一列出理由。
1.编译延迟
DataBinging的编译不是及时的,我们在xml文件写好布局后,并不能直接就可以找到xml文件对应的Binding类,而要 Rebuild Project后才能找到Binding类,在xml文件添加某个控件的id后,也不能直接引用这个控件,也要Rebuild Project,实际上对xml文件的任何修改,都要Rebuild Project,databinding的相关才会生效,而不像R文件,我们修改后不必做额外的操作,R文件就会更改。而这会影响到编码速度。
2.无用功能多
DataBinding可以在xml文件直接绑定点击事件,可以在属性被改变时(DataBinding的方式改变)触发绑定的事件,然而这些看起来很美的功能,实质上从没被我使用过。
3.布局文件复杂
我们可能会写下如下代码:
<data>
<variable
name="bean"
type="***.ConsignmentDetailBean"/>
</data>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f4f4f4"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="15dp"
android:text="@{bean.createTime}"
android:textColor="@color/colorTextWhite"
android:textSize="15sp"
tools:text="2018/08/12 12:20:20" />
</LinearLayout>
通过网络请求获取到数据实体类后,使用mBinding.setBean(bean);
来把数据设置上去,然而当我们要对获取的时间做一些格式上的设置的时候,我们就要先写好一个时间转换的类,再如下调用:
<import type="com.saiot.steward.baseLib.util.TimeUtil"/>
android:text="@{TimeUtil.formatTime(bean.createTime)}"
当然你也可以在实体类的get方法里做处理,但DataBinding的处理确实要麻烦些。因为DataBinding直接支持的函数很有限。
而如果没使用DataBinding,我们直接在set时做下格式处理就好了。
还有一种情况,例如界面要如下显示:”今日待办(10)”,然后后台给我们的接口返回的是10,那么我们在DataBinding上要如此做:
android:test="{@string/a+bean.value+@string/b}"
其中a和b分别是定义在资源文件的”今日待办(”和”)”,而不能直接在XML文件拼接。
4.多模块开发
如果以上问题都是些不够方便的小问题,我还可以忍受,那它在多模块开发上的问题是我放弃它的最主要原因。
DataBinding在多模块开发的时候,有这样一个机制:
- 如果子模块使用了DataBinding,那么主模块也必须在gradle加上配置,不然就会报错;
- 如果主模块和子模块都添加上了DataBinding的配置,那么在编译时,子模块的XML文件产生的Binding类除了在自己的build里会有一份外,在主模块下也会有一份。
那么,如果主模块与子模块都有一个layout根目录的activity_main.xml,主模块生成的ActivityMainBinding会是根据子模块的文件生成的!这种情况我们还可以通过让主模块和子模块使用不同的命名,那么下面这个问题就跟要命了:
如果子模块的某个xml文件使用了一些第三方的控件,那么主模块由于也会生成这个文件的Binding类,并且其会有第三方控件的引用,这时候由于主模块没有引入这些控件,就会报错,解决办法是在子模块应用第三方控件的时候,使用api的方式应用,这样主模块就坚决引用到了这些第三方控件,这是这样违背了解耦的原则。