Jetpack系列
Android Jetpack WorkManager初级认识
Android Jetpack ViewModel由浅入深
附上官网地址https://developer.android.com/topic/libraries/data-binding/expressions
一、DataBinding的定义及作用
是一个支持库,使用该库,您可以使用声明性格式而非编程方式将布局中的UI组件绑定到应用程序中的数据源。不需要在使用findViewById之类的,布局文件也不再简单的是一个布局文件,可以包含数据以及逻辑。
配置必要信息
在Build.gradle
文件添加下面信息
android {
...
dataBinding {
enabled = true
}
}
二、基本使用
1. 简单展示绑定过程
- 新建
activity_databinding.xml
// 定义数据的标签
// 定义布局的标签
上面的格式:
包含两个子标签,
-
定义我们的数据的地方,
-
,这个布局就相当于我们平时的布局。
TextView
的text
绑定了android:text="@{title}"
,如果第一次设置title
数据变化,页面就会跟着变化。
这里解释一下
标签中的属性,
name
是定义的变量名
type
是变量的类型
- 新建
Acitivity
绑定布局
class DatabasingActivity : AppCompatActivity() , View.OnClickListener {
lateinit var mactivityBinding: ActivityDatabindingBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//绑定布局
mactivityBinding = DataBindingUtil.setContentView(this,R.layout.activity_databinding)
mactivityBinding.title = "基础使用"
}
}
上面的ActivityDatabindingBinding
是系统自动帮我们生成的,使用DataBindingUtil.setContentView(this,R.layout.activity_databinding)
便可以绑定好布局,(不需要像以前调用setContentView()
),mactivityBinding.title = "基础使用"
赋值给title
,textView
就会自动展示出数据了。
注意点:
ActivityDatabindingBinding
是根据你的布局.xml
去生成的 这里的是activity_databinding.xml
所以生成ActivityDatabindingBinding
.- 如果发现
databinding
生成的ActivityDatabindingBindingImpl
(看自己的命名)中出现路径报错,那么最大的可能性是你的.xml
文件里面写错了之类的!!!
下面看一下.xml
文件支持什么表达式。
三、支持的表达式:
- 数学计算符 + - / * %
- 字符连接符号 +
- 逻辑运行符号 && ||
- 二元运行符号 & | ^
- 一元运行符号 + - ! ~
- 移位 >> >>> <<
- 比较符号 == > < >= <=(请注意,<必须转义为<)
- instanceof
- Grouping ()
- character, String, numeric, null
- cast
- 方法调用
- 现场访问
- Array存取 []
- 三元运算符 ?:
四、 不支持的表达式:
- this
- super
- new
- explicit generic invocation (显式泛型调用)
五、 设置点击事件跟导入数据类
- 新建数据实体类
data class Person(var Name:String,var Age:Int)
- 修改一下布局文件
//关键点1
//关键点2
//关键点3
//关键点4
//关键点4
关键代码1:
导入数据类所在的路径包名,要导入后才能使用
关键代码2:定义Person
类型的变量
关键代码3:定义android.view.View.OnClickListener
View的点击事件
关键代码4:在Button
的android:onClick="@{onClickListener}
中引用关键代码3
定义的点击事件
3 修改一下Activity
文件
class DatabasingActivity : AppCompatActivity() , View.OnClickListener {
lateinit var mactivityBinding: ActivityDatabindingBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//绑定布局
mactivityBinding = DataBindingUtil.setContentView(this,R.layout.activity_databinding)
//赋值给布局中定义的中的面的peronInfo
mactivityBinding.peronInfo = Person("man",18)
//实现布局中定义的中的onClickListener变量,这里传入this,记得要实现接口
mactivityBinding.onClickListener = this
}
//当点击按钮的时候就会自动调用到这里了
override fun onClick(v: View?) {
when(v){
mactivityBinding.button7 -> {
mactivityBinding.textView.text = "这个是点击button7产生的"
}
mactivityBinding.button8 ->{
mactivityBinding.textView2.text = "这个是点击button8产生的"
}
}
}
}
直接看上面注释就知道用法了
上面的注释看懂就可以了,Activity中基本的DataBinding你就算是掌握了,关于点击事件的还有很多种写法,可能需要重新写一篇详细的说一下其它的细节吧。
六、在Fragment中使用
lateinit var fragmentTestBinding:FragmentTestBindingBinding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
fragmentTestBinding = DataBindingUtil.inflate(inflater,R.layout.fragment_test_binding,container,false)
return fragmentTestBinding.root
}
跟Activity
对比Fragment
这里就是DataBindingUtil.inflate()
传参不同,然后返回fragmentTestBinding.root
。其它的操作都是一样的
七、单向绑定数据(可观察的数据对象)
最开始使用的时候我很不理解为什么还有个单向绑定。因为我看到基本类型的数据,在
xml
中data
定义 然后再Activity
中更改,页面会跟着一起刷新,这不就是相当于单向绑定了吗???直到后面我在节点中
import
入自定义的数据类bean
,然后再在Activity
中更改bean
中的成员变量时,页面并没有改变。这时候我才懂了这个存在的原因。(ps:这个只是个人刚接触的时候想法,新手有可能也有会这样想法,我这里先说一下)
官网定义:任何普通的旧对象都可以用于数据绑定,但是修改对象不会自动导致UI更新。数据绑定可用于使您的数据对象在数据更改时通知其他对象(称为侦听器)。有三种不同类型的可观察类: 对象,字段和集合
实现的基本方法有以下几种
1. 直接定义可监听变量
ObservableBoolean
ObservableByte
ObservableChar
ObservableShort
ObservableInt
ObservableLong
ObservableFloat
ObservableDouble
ObservableParcelable
//定义的实体bean时候
class Person {
val Name = ObservableField()
val Age = ObservableInt()
}
//(kotlin 语法 )调用实体bean的时候
user.firstName = "Google"
val age = person.Age
--------------------------------------------------------
//(java 语法 )调用实体bean的时候
person.firstName.set("Man");
int age = person.Age.get();
使用的时候记得使用
get()
,set()
方法。(ps:kotlin语法看来起来是直接调用的,但实际上里面也是实现了get()
,set()
方法)
//可监听变量数组类型
ObservableArrayMap<>()
ObservableArrayList<>()
----------定义xml文件-----------------------
…
}
------------使用的时候----------------------------
ObservableArrayList().apply {
add("man")
}
用法跟基本类型一致,但是有两点要注意
- 记得在
中
import
入对应的数组的包名所在路径- 引用这些集合类型的时候,
<
要改为\<
(ps:Android stuido会提醒你这样子操作的 )
2. ObservableField,这个跟上面那些用法一样,泛型传入指定类型。
3. 继承 BaseObservable()
-------------------------------kotlin写法-----------------------------
class User :BaseObservable(){
@get:Bindable
var name:String = ""
set(value) {
field = value
notifyPropertyChanged(BR.name)
}
@get:Bindable
var age:Int = 0
set(value) {
field = value
notifyPropertyChanged(BR.age)
}
}
--------------------------------java写法---------------------------------
private static class User extends BaseObservable {
private String firstName;
private String lastName;
@Bindable
public String getFirstName() {
return this.firstName;
}
@Bindable
public String getLastName() {
return this.lastName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
notifyPropertyChanged(BR.firstName);
}
public void setLastName(String lastName) {
this.lastName = lastName;
notifyPropertyChanged(BR.lastName);
}
}
实体类继承BaseObservable()
- 在对应的字段
get
方法钱前面加上注解@Bindable
,kotlin
写@get:Bindable
- 在
set
方法中修改数据后调用notifyPropertyChanged(BR.name)
通知更改数据 - 如果数据类的基类不能被改变,可观察到的界面可以实现使用
PropertyChangeRegistry
对象注册和通知监听器。(补充)
这里有个坑!!! BR总是报错 找不到
name
跟age
字段,后来百度需要在对应module
项目下的build.gradle
上面加上插件
apply plugin: 'kotlin-kapt'
八、双向绑定数据
在xml文件中 单向绑定我们是用@{变量名}
,双向绑定则是@={变量名}
最常见的需求就是我们的页面输入了。输入的数据要在代码中可以让我们接收到。
当editText
数据数据的时候android:text="@={title}"
双向绑定数据,TextView
中绑定的 android:text="@{title,default =标题}"
也会跟着一起变化。
九、在include中使用
在include中:
先定义include_text.xml
在布局中引入
在include
标签中app:peronInfo
将数据传入,这里的peronInfo
是在include
布局中我们自己定义的数据。
十、在viewStub中使用
因为viewStub是属于懒加载的布局,如果不调用inflate,就不会加载。属于安卓上面也是页面优化有一个范畴。
先定义一个viewStub
布局页面
在布局中引入
以上的操作跟include
的用法一致,不同点在于Activity
中的绑定
Activity
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//绑定布局
mactivityBinding = DataBindingUtil.setContentView(this,R.layout.activity_databinding)
o.add(0,"第一数据")
mactivityBinding.peronInfo = Person("man",18,o)
mactivityBinding.viewStub.viewStub!!.inflate()
}
关键代码mactivityBinding.viewStub.viewStub!!.inflate()
这里就是加载viewStub的地方。
十一、在Adapter中的使用
简化统一可以使用的ViewHolder
public class BaseViewHolder extends RecyclerView.ViewHolder {
public BaseDataBinding mbinding;
public BaseViewHolder(BaseDataBinding binding) {
super(binding.getRoot());
mbinding = binding;
}
}
你可以使用上面的ViewHolder
就可以不用自己总是去写ViewHolder
了。
val listItemBinding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false)
在Adapter
的onCreateViewHolder
中可以使用上面的方法绑定布局
关于Adapter
的DataBinding
使用的网上有很多文章大家可以自行查阅
这篇文章主要是记录一下自己学习的过程,很多细节化跟封装的话以后再出一篇文章另外记录,有问题的也请同学们在评论区留言,希望看的同学们觉得有用的话给个赞~ 谢谢