一、配置
在应用的build.gradle里面加上
android {
'''
dataBinding {
enabled = true
}
'''
}
二、布局和绑定表达式
1、建立实体类User
data class User(val firstName: String, val lastName: String)
2、xml布局文件,数据绑定布局文件,以根标记 layout 开头,后跟 data 元素和 view 根元素。
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="user" type="com.example.myapplication.entity.User"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.firstName}" />
</LinearLayout>
</layout>
3、绑定数据
a、activity中使用,ActivityMainBinding是自动生成的,根据基于布局文件的名称,比如布局文件名为 activity_main.xml,因此生成的对应类为 ActivityMainBinding。
如果实在找不到,可以在java(generated)查看
image.png
val binding: ActivityMainBinding = DataBindingUtil.setContentView(
this, R.layout.activity_main)
b、如果在fragment、listview、recyclerview中使用,可以使用DataBindingUtil.inflate
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val fragmentOneBinding = DataBindingUtil.inflate<FragmentOneBinding>(layoutInflater,R.layout.fragment_one,container,false);
fragmentOneBinding.user = User("zhang","san");
return fragmentOneBinding.root;
}
4、表达式语言
算术运算符 + - / * %
字符串连接运算符 +
逻辑运算符 && ||
二元运算符 & | ^
一元运算符 + - ! ~
移位运算符 >> >>> <<
比较运算符 == > < >= <=(请注意,< 需要转义为 <)
instanceof
分组运算符 ()
字面量运算符 - 字符、字符串、数字、null
类型转换
方法调用
字段访问
数组访问 []
三元运算符 ?:
android:text="@{String.valueOf(index + 1)}"
android:visibility="@{age > 13 ? View.GONE : View.VISIBLE}"
android:transitionName='@{"image_" + id}'
5、事件处理
a、方法引用
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="user" type="com.example.myapplication.entity.User"/>
<variable name="handler" type="com.example.myapplication.fragment.OneFragment"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:layout_width="wrap_content"
android:id="@+id/text_tv"
android:layout_height="wrap_content"
android:text="@{user.firstName}"
android:onClick="@{handler.testClick}"
/>
</LinearLayout>
</layout>
class OneFragment : Fragment() {
fun testClick(view: View){
Log.d("hah","hahaha"+view.toString());
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val fragmentOneBinding = DataBindingUtil.inflate<FragmentOneBinding>(layoutInflater,R.layout.fragment_one,container,false);
fragmentOneBinding.user = User("zhang","san");
fragmentOneBinding.handler = this;
return fragmentOneBinding.root;
}
}
注意fragmentOneBinding.handler = this;这一句话不要漏掉
b、监听器绑定
监听器绑定是在事件发生时运行的绑定表达式。它们类似于方法引用,允许运行任意数据绑定表达式。
fun testClick1(user:User){
Log.d("hah","hahaha"+user);
}
<TextView android:layout_width="wrap_content"
android:id="@+id/text_tv"
android:layout_height="wrap_content"
android:text="@{user.firstName}"
android:onClick="@{()->handler.testClick1(user)}"
/>
如果要把点击的view也传递过去,需要
fun testClick2(view: View,user:User){
Log.d("hah","hahaha"+user+view.toString());
}
<TextView
android:id="@+id/text_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{(view)->handler.testClick2(view,user)}"
android:text="@{user.firstName}" />
6、使用可观察的数据对象
可观察性是指一个对象将其数据变化告知其他对象的能力。通过数据绑定库,您可以让对象、字段或集合变为可观察。可观察类有三种不同类型:对象、字段、集合
ObservableBoolean
ObservableByte
ObservableChar
ObservableShort
ObservableInt
ObservableLong
ObservableFloat
ObservableDouble
ObservableParcelable
可观察字段
可观察字段是具有单个字段的自包含可观察对象。原语版本避免在访问操作期间封箱和开箱。如需使用此机制,创建只读属性
class User {
val firstName = ObservableField<String>()
val lastName = ObservableField<String>()
val age = ObservableInt()
}
user.firstName.set("dddd");
Log.d("haha",user.firstName.get()!!);
可观察集合
val map = ObservableArrayMap<String, Any>().apply {
put("firstName", "Google")
put("lastName", "Inc.")
put("age", 17)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val fragmentOneBinding = DataBindingUtil.inflate<FragmentOneBinding>(
layoutInflater,
R.layout.fragment_one,
container,
false
);
fragmentOneBinding.user = map;
return fragmentOneBinding.root;
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
map.put("firstName","hhhhhhh")
}
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="androidx.databinding.ObservableMap"/>
<variable name="user" type="ObservableMap<String, Object>"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/text_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.firstName}" />
</LinearLayout>
</layout>
不要忘记 fragmentOneBinding.user = map;
c、绑定适配器
可以给一类操作命名直接在xml里面调用
比如,我有Imageview,实际每次都是传入Url加载进控件
在app的gradle里面添加
plugins {
id 'kotlin-kapt'
}
定义一个object类,例如
object ImageUtil {
@BindingAdapter("imageurl")
@JvmStatic
fun loadImage(view: ImageView, url: String) {
Glide.with(imageview).load(url).into(imageview)
}
}
在布局文件里使用
<ImageView
android:id="@+id/haha"
imageurl="@{user.profileUrl}"
android:layout_width="200dp"
android:layout_height="200dp" />
@BindingAdapter("imageurl")的imageurl对应布局文件里面控件的imageurl,布局文件传入的字符串会调用到被@BindingAdapter("imageurl")注解的方法。
注意:被@BindingAdapter注解的方法必须为static方法,并且要加@JvmStatic注解,不然会报错,如下
java.lang.IllegalStateException: Required DataBindingComponent is null in class FragmentOneBindingImpl. A BindingAdapter in com.example.myapplication.fragment.ImageUtil is not static and requires an object to use, retrieved from the DataBindingComponent. If you don't use an inflation method taking a DataBindingComponent, use DataBindingUtil.setDefaultComponent or make all BindingAdapter methods static.
网友评论