• 四月
  • 16
  • 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,将会自动生成如下

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把坑踩够再说!

 

原创文章,转载请注明出处

正在加载评论...

0 / 240

警告

确定