- 四月
- 16
- load
- load
通过踩坑的方式了解databinding基础用法 2021-04-16 22:46:41
databinding是什么?
databinding,google发布的数据绑定框架,可用于mvvm的实现,能够省去findviewbyId。
在databinding下如此即可
眼熟,这不就是kotlin的synthetic吗?而且kotlin更方便呢。
没错,在kotlin和synthetic配合下,确实更为方便,但是,在Kotlin 1.4.20中,JetBrains废弃了Kotlin Android Extensions。主要原因如下:
- 污染全局命名空间
- 不能暴露可空性信息
- 仅支持kotlin
因此,官方建议的替代方案,则是viewbinding,不过今天我们主要介绍的是databinding,在这里viewbinding就简单说明与databinding有什么区别吧
databinding和viewbinding的区别?
功能上,viewbinding能做的,databinding也能做,但databinding会做得比viewbinding麻烦一些,而且效率也没有viewbinding好(注释处理器会影响数据绑定的构建时间)。
但databinding的亮点在于,可用于实现mvvm设计模式,viewbinding则是更麻烦的synthetic。
如果没有mvvm使用需求,使用viewbinding即可。
实践:
一.打开databinding
如果你的android studio不是4.0或以上,需要这么做
二.修改你的布局
打开你需要修改的layout,点击根布局(如ConstraintLayout),alt+enter,选择Convert to data binding layout,将会自动生成如下
三.视图绑定
只要布局转换成data binding layout,那么你的activity就不能使用setContentView渲染界面
这里你可能就产生疑问了,ActivityMainBinding是什么东西?
这是databinding自动生成的数据绑定类名字是对应layout,我的layout叫activity_main,因此它就叫ActivityMainBinding
你以为视图绑定这就完了?实际上它并不像kotlin的synthetic那么便捷,在fragment,dialog,自定义view,甚至动态创建的view(如recyclerview的item),都有它们自己的绑定方式。
在fragment下:
在dialog下:
在自定义view下
在adapter等动态创建的view下
四.数据绑定
也许你会开始想,项目是纯kotlin开发的,为了弥补synthetic的缺陷,却要遵守它那么多规矩,规避synthetic的缺陷不是更简单吗?
其实,前面说的,都只是视图绑定,databinding翻译过来就是数据绑定,数据绑定才是它擅长的领域。
先看我们转换后的layout
如果你仅仅是为了当viewbinding使用,data标签可以删掉
layout,就是把data和你的root layout包裹起来的东西,无需在意是什么
至于data,就是databinding的核心所在,它可以让你的layout充满活力。
我们先来个简单的示范,在data创建一个字符串变量,并绑定到一个view里
代码区:
数据这么一绑定,连text都不需要了,甚至可以同时绑定多个view
代码区,依然只有这一行代码,但同时修改了textview和edittext的text:
它还支持一些运算符,java支持的,它大多都支持。
算术 + - / * %
字符串合并+
逻辑&& ||
二元& | ^
一元 + - ! ~
移位>> >>> <<
比较== > < >= <=
Instanceof
Grouping ()
character, String, numeric, null
Cast
方法调用
Field 访问
Array访问 []
三元?:
如三元
代码
注意:layout访问对象或常量,就像你的代码想调用某个对象,需要事先import
方法调用:
首先定义一个数据类
然后你的layout需要引入
代码区
有同学会3联想到,既然是mvvm,只要我修改了model里面的内容,那么text也会相应改变的吧?
很遗憾,如果你这么写,甚至连编译都办不到。
Smart cast to 'HomeModel' is impossible, because 'binding.model' is a complex expression
那既然是同一个对象,我能不能放出来写?
不能说不可以,这样写确实可以把title换了,但如果你把修改的过程延迟修改,或者放在事件里,那只会得到意料以外的结果
日志输出:
界面:
怎么回事,说好的mvvm呢?为什么没有自动刷新ui?其实,我们的model还需要做点什么,这个数据绑定只是刚刚开始。
关于数据绑定,这里分为两种,分别为单向数据绑定、双向数据绑定。
数据绑定,这里有三种处理方式,分别是:
- BaseObservable
- ObservableField
- ViewModel
BaseObservable:
1.我们的model要继承BaseObservable
2.把需要绑定的数据,在get加上@Bindable注解
3.在set处添加notifyPropertyChanged(局部刷新)或notifyChange(全局刷新)刷新你的字段
这个时候,修改你的model就可以同步刷新ui了。不过吧,既然这是单向数据绑定,那么,如果通过findviewById等其它形式,修改了这个text值,是获取不到新的text值的,例如这样
代码
改成双向也很简单,把你的layout,@{model.title}改成@={model.title}即可
ObservableField:
我们的model往往都需要继承一个属于自己项目的BaseModel,而项目的BaseModel可能还需要继承别的东西。
继承也算了,还要加注解,还得自己去notifyChange,导致我们使用的kotlin,不能用data class,可见BaseObservable并不是优选。那么我们可以使用第二种方法,ObservableField
使用方法和BaseObservable相似,不同的是,你不能直接取值或赋值
至于ObservableField是什么?ctrl点进去后不难发现,它继承了BaseObservableField,而BaseObservableField继承的则是BaseObservable,再看看set
从结果而言,还是用了BaseObservable,而且性能怎么都没有直接用BaseObservable高。
ViewModel
前两个提到的,都只是mvvm里的model,viewmodel也是可以进行数据绑定的,还可以处理业务逻辑
但viewmodel机制需要另开一贴才能介绍,这里就简单介绍如何配合databinding,以及注意事项。
首先,创建一个HomeViewModel,并继承AndroidViewModel。
也可以继承ViewModel,和AndroidViewModel的区别不过是,AndroidViewModel继承了ViewModel,并提供了application,ViewModel则不会,两则没太大差距。
创建,和ObservableField相似,创建需要修改的字段,不同的是,要改名为MutableLiveData
layout
activity
这看起来我直接用ObservableField更方便呀?
刚刚也提到了,前两个都是model,这个是viewmodel,放在mvp这个就是persenter了,如果是为了用model,前两个根据个人需求选择即可。
主要就注意一点,不要让viewmodel持有activity对象,如果没有适当清理,会造成内存泄漏!
至于viewmodel有什么特征,方便的时候另开一贴详细介绍一下。
六.BindingAdapter
前面提到的,我们都仅仅是绑定text,而textview存在一个叫setText的方法,databinding绑定数据的前提,必须要存在set方法,如textSize,它恰好存在setTextSize,因此我们是可以直接把数据绑定上去的。
但类似layout_width这样的属性,并不存在一个叫setLayoutWidth的东西,这个时候,我们需要自己创建一个绑定适配器
任意地方创建一个object BindingAdapters,代码如下:
layout
activity
有同学产生疑问了,default是什么东西?
在我们绑定数据之前,这里实际是不存在任何值,那么,这里,就是它的默认值。
但这个默认值,最好还是来自value,直接用常量可能会发生无法预料的问题,调试甚至会让你抓狂。
default这个疑问解开了,但新的问题来了,如果我在别的地方,例如就我的activity,也绑定了一个android:layout_width,它会使用哪个?
虽说databinding允许你这么做,但它不会基于就近而决定调用哪个方法,但它会调用其中一个。为了减轻自己的开发成本,不要那么做。
我想另一个界面,它的width我希望有别的规则,例如赋值后需要乘2,如何实现?
那就是不用android:layout_width,而是创建一个新的属性,用于width赋值。
在BindingAdapters多创建一个函数
layout
注意:view要求width是需要赋值,最起码也要有个0dp
activity
看起来BindingAdapter连attr都替我们省了。
在这里,databinding的基本使用就介绍完毕了,不过不建议刚看完就在项目中使用,建议先写点小demo玩玩,例如写个贴吧部分功能啥的。
因为这玩意一旦出错了,所报错的信息是很坑的,你根本不知道错在哪。
至少先在自己写的小demo把坑踩够再说!
原创文章,转载请注明出处