这里还需要相应添加一个key,因为java的字符串是不支持单引号和双引号一起使用的,在xml中使用时需要。
接下来就是对map进行赋值了,这里需要注意,map和key需要同时设置,不然在xml中绑定了是拿不到值的。
2.在xml中进行运算符操作
在使用了DataBinding的xml中可以使用简单运算符操作,比如,我们可以用取到的数字源进行操作后再设置到控件上,这里举一个例子,我们在获取的值后面加一个单位。需要注意的是,在这里拼接字符串需要使用的并不是单引号,而是数字1左边的那个键。
除了上面用到的字符串拼接以外,还支持另外一些操作,具体见下图,注意并不是所有的符号都支持。
3.双向绑定
什么是双向绑定?
前面的实现都是单向的绑定操作,也就是说数据源改变以后会自动更新到控件上。但是,如果想让控件的值被用户手动输入变化后也能自动地同步到数据源里,这个操作就叫做双向绑定。
双向绑定以后可以实现什么效果?
为了演示一下双向绑定的效果,我给页面上加了一个输入框以及一个文本框,它们都使用的同一个数据源。当用户给输入框删除或者输入新数据以后,这二者虽然使用的同一份数据源,但是由于输入框输入的内容并没有同步到数据源中,所以文本框的数据并不会自动地刷新成用户在输入框中输入的值。
而双向绑定以后是这样的,输入框不管是删除还是输入,都会立即自动把结果同步到文本框上
如何实现双向绑定呢?
双向绑定具体做法是将@{}改成@={}。如下图,在将EditText的值与数据源双向绑定了以后,当用户在输入框中输入内容以后,由于输入框的值会同步到二者共用的数据源中,下面的TextView内容就会自动跟着变化。
4.通过BindingAdapter来自定义Setter
有些控件的属性并不是直接显示在控件上的,而是需要经过处理甚至是第三方API的处理才能使用。又或者是想要覆盖系统自身的属性,也可以,总之就是这里定义的对属性的BindingAdapter注解处理方式会覆盖系统的方式。
比如想要将url设置到ImageView上,需要通过Picasso或者Glide来将url下载转成bitmap来设置,这个时候就需要特殊处理。
首先在Bean里新增一个String类型的url字段,然后在ImageView上自定义一个url属性,将其绑定到url字段上。也可以定义多个,这里多定义了一个error属性。
最后处理一下实际的将url设置到ImageView上的操作
5.设置数据到列表控件中
以RV为例,接下来说一下如何将数据设置到列表控件中,这也是非常常见的操作了。由于列表控件是有Adapter的,相当于设置数据时多传了一层。
这是一个并没有使用DataBinding的简单RecyclerView示例,里面有3种不同布局,当然这里代码写得很不规范,因为这个不是重点。
运行以后大致的效果如下,为了区分三种不同的Item,我将每个Item显示的TextView个数进行了区分,方便大家看懂这是不同的item。
接下来我们要做让它绑定到DataBinding,实现当数据源变化时不调用nofigyDataSetChanged方法来实现Item数据发生变化。
使用步骤参照之前基本使用来即可,第一步新建一个Bean作为DataBinding获取数据库的地方。第二步将那3个item都变成layout包裹的DataBinding布局。
第三步是将当前布局交给DataBinding进行托管
第四步是需要修改一个ViewHolder的实现,由于之前是将View托管到了ViewDataBinding中,所以需要View的时候可以从托管平台DataBinding来获取。这里保存下binding是为了在onBindViewHolder中绑定数据用,要记住现在需要数据都是从ViewDataBiding中获取了,而不能直接从values数组里去获取,不然数据修改了是刷新不了的。这里实现一个接口,是为了偷懒,在onBindViewHolder中统一处理。
最后在onBindViewHolder中调用系统的setVariable方法对DataBinding进行赋值,相比最初的根据position进行判断布局,然后再进行赋值是不是节省了很多代码哈哈,请看下图:
最后,验证一下数据修改时,会自动刷新到rv上吧,我这里开了个线程,每秒修改一下rv上的数据源,注意我只是修改了数据源并没有notifyDataSetChanged。
[图片上传失败…(image-3a755f-1592979137700)]
让我们来看一下最终的效果,符合预期。
上源码(划重点)
1、DataBindingUtil是个什么类?
在使用DataBinding的时候,一般第一件事情是初始化DataBinding,代码大概如下:
final DataBindingTest viewDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
final TestBean testBean = new TestBean();
viewDataBinding.setTestVariable(testBean);
那么DataBinding究竟是何方神圣呢,我们打开该类的属性和方式视图,如下:
这里mapper是调用DataBindingUtil.setContentView初始化DataBinding时用来将layoutid和实际实现类进行映射的一个DataBinderMapperImpl对象,在下面讲解DataBinding初始化的时候还会讲到。sDefaultComponent是预留给开发人员设置的一个属性,默认为null,也会体现在后面DataBinding初始化的过程中。
其中inflate方法是初始化DataBinding方法的另一种方式,在后面给recyclerview上使用DataBinding的例子中会详细讲到,具体代码大概是这样子的:
ViewDataBinding viewDataBinding = DataBindingUtil.inflate(MainActivity2.this.getLayoutInflater(),R.layout.rv_layout1,parent,false);
其中bind()方法也和上面的Inflate方法类似,也是用来初始化DataBindingUtil的方式,和setContentView方法依然类似,这三者功能基本是一样的。
下面的findBinding方法和getBinding方法都是对外提供的static方法,用来返回生成的ViewDataBinding类的,通过这些方法我们可以根据View对象或者布局Id来获取绑定好的ViewDataBinding对象。
convertByIdToString后面也会讲到,是系统提供给我们的对外接口,具体很少使用,看注释是有利于打日志。
bindToAddedViews是调用DataBindingUtil.setContentView()进行绑定的时候会调用的中间方法,目的是为了区分当前是不是只有一个控件,进行一些特殊处理,在讲DataBinding初始化的时候也会讲到。
2、DataBinding初始化的时候都做了什么事情
我们在Activity中使用DataBinding的时候,需要进行初始化,代码大致是这么写的:
DataBindingUtil.setContentView(this, R.layout.activity_main);
我们点进去看下都做了什么操作,可以看到很简单,首先调用了Activity的setContentView方法,这个是不使用DataBinding的时候也需要调用的,其次是调用了bindToAddedViews方法,调用的时候将最外层的Framlayout容器以及布局的LayoutId给传了进去。
在bindToAddedViews方法中,不管走哪个判断分支,是走到了bind方法,其中第一个参数component默认是null,除非咱们手动去设置。第二个参数是所有view的数组,第三个是布局文件Id。
接着往下面看,是调用到了一个Mapper对象的getDataBinder方法
Mapper对象是一个DataBinderMapper抽象类的子对象,这个抽象类代码如下:
实现了DataBinderMapper抽象类的具体子类是DataBinderMapperImpl类,该类的getDataBinder()方法具体代码如下:
ViewDataBinding getDataBinder(DataBindingComponent component, View view, int layoutId) {
switch(layoutId){
case LAYOUT_AAA:
return new AaaBindingImpl(component, view);
case LAYOUT_BBB:
return new BbbBindindImpl(component, view)
}
}
这段代码十分地简单,就是初始化了相应的DataBinding类,没什么好说的,还有就是保存好了所有的布局文件id、Variable名、到一个map中,一直findUseage你会发现最终是在DataBindingUtil类中的convertByIdToString方法使用,该方法是暴露给开发人员的public方法,说明是预留给我们使用的功能,查看方法提示大概是可以用来和日志有关系?
3、setVariable数据更新流程是怎么样的
首先点进去看下,它是ViewDataBinding该抽象类中的抽象方法。ViewDataBinding类是系统生成的抽象类
接下来我们看看它的实现类有哪些,这很明显是每个DataBinding的布局文件生成了一个,命名是以布局文件的首字母大写然后驼峰的方式,最后拼上了BindingImpl,当然这个名字是可以自定义的,注意看第二个实现类名不一样,这是因为我们在布局文件中自定义了其名字。
接下来我们随便点进去一个类吧,查看一下其setVariable方法
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
最后
只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。
真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。
腾讯、字节跳动、阿里、百度等BAT大厂 2019-2021面试真题解析
资料太多,全部展示会影响篇幅,暂时就先列举这些部分截图
面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-pYqnKb0f-1711745646085)]
最后
只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。
真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。
[外链图片转存中…(img-uUUmb04o-1711745646086)]
腾讯、字节跳动、阿里、百度等BAT大厂 2019-2021面试真题解析
[外链图片转存中…(img-WZaf8x78-1711745646086)]
资料太多,全部展示会影响篇幅,暂时就先列举这些部分截图