一、布局定义
1.和相关
使用DataBinding,布局最外层一定是
如果是使用标签,那么一般用来定义变量,或者导包。
1 2 3 4 5 6 | <data> <variable name="viewModel" type="com.xxx.demo.ui.viewmodel.LoginViewModel" /> </data> |
1 2 3 4 5 6 7 8 9 10 11 12 13 | <data> <import type="com.xxx.demo.R" alias="appR" /> <import type="com.xxx.demo.ext.UtilsExtKt" alias="utilsExtKt" /> <variable name="viewModel" type="com.xxx.demo.ui.viewmodel.ProfileViewModel" /> <variable name="user" type="com.xxx.demo.model.bean.User" /> <variable name="show_collect" type="boolean" /> </data> |
如果是在标签中导包,也是使用
2.在布局中的使用
(1)单向绑定
1 2 3 4 5 6 7 | <androidx.appcompat.widget.AppCompatEditText android:id="@+id/et_username" android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" android:text="@={viewModel.username}" bindingadapter:afterTextChanged="@{viewModel.verifyInput}" /> |
单向数据绑定,其实就是刷新对应的实体或者属性,则刷新视图。但是视图的变化并不会更新实体或者对应的变量的值
(2)双向绑定
1 2 3 4 5 6 7 8 | <androidx.appcompat.widget.AppCompatEditText android:id="@+id/et_password" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textPassword" android:singleLine="true" android:text="@={viewModel.password}" bindingadapter:afterTextChanged="@{viewModel.verifyInput}" /> |
实体或者变量刷新,会更新视图;而视图变化也会更新对应的实体或者变量
(3)设置默认值
因为viewModel.username初始没有值,所以在刚进入页面的时候,会没有任何显示,那么可以使用default显示默认值
1 | android:text="@{viewModel.username,default=@string/profile_login_or_register}" |
如果是直接写字符串,那么就是default=用户名这样的写法,不需要加眼号
也可以设置默认的visibility,比如:
1 | android:visibility="@{shouldBeVisible ? View.VISIBLE : View.GONE, default=View.GONE}" |
(4)DataBinding在XML中绑定数据支持的表达式
数学 + - / * %
1 2 3 4 | <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{article.zan + 1,default = 2}"/> |
字符串连接 +
1 2 3 4 | <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{article.superChapterName+'/'+article.chapterName}" /> |
字符串拼接的用法,其实就是与正常拼接一样
逻辑 && ||
二进制 & | ^
一元运算 + - ! ~
三元运算 ?:
判断是否为空 ??(例:android:text="@{user.name ?? user.defaultName}",相当于android:text="@{user.name !=null ? user.name : user.defaultName}")
位运算 >> >>> <<
1 2 3 4 | <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{((article.zan >> 2) >= 10) ? @string/profile_my_collect:@string/profile_personal_center}" /> |
比较 == > < >= <=
1 2 3 4 | <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{(article.zan >= 10) ? @string/profile_my_collect:@string/profile_personal_center}" /> |
instanceof
方法调用
1 2 3 4 5 6 7 8 9 10 11 12 13 | <androidx.appcompat.widget.AppCompatButton android:id="@+id/btn_login" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="@dimen/dp_20" android:layout_marginTop="@dimen/dp_20" android:layout_marginEnd="@dimen/dp_20" android:background="@drawable/bg_btn" android:enabled="@{viewModel.uiState.enableLoginButton}" android:onClick="@{()->viewModel.login()}" android:text="@string/login" android:textColor="@color/white" android:textSize="@dimen/sp_16" /> |
方法的调用,采用@{()->viewModel.login()}的方式,类似于lambda表达式
前面的()表示参数
变量引用
获取数组、集合、Map的值 []
1 2 3 4 5 6 7 8 9 10 11 12 13 | <data> <import type="android.databinding.ObservableMap"/> <variable name="user" type="ObservableMap<String, Object>"/> </data> … <TextView android:text='@{user["name"]}' android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView android:text='@{String.valueOf(1 + (Integer)user["age"])}' android:layout_width="wrap_content" android:layout_height="wrap_content"/> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <data> <import type="android.databinding.ObservableList"/> <import type="com.example.my.app.Fields"/> <variable name="user" type="ObservableList<Object>"/> </data> … <TextView android:text='@{user["name"]}' android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView android:text='@{String.valueOf(1 + (Integer)user["age"])}' android:layout_width="wrap_content" android:layout_height="wrap_content"/> |
3.使用@BindingAdapter
首先@BindingAdapter(value = ["flowAdapter"]),value是定义的一个类似于自定义View的属性,用于扩展View的属性
Java的方式:
1 2 3 4 5 6 | public class CustomBindingAdapter { @BindingAdapter("visibleGone") public static void showHide(View view, boolean show) { view.setVisibility(show ? View.VISIBLE : View.GONE); } } |
Java的方式实现,第一个参数作为View,是定义扩展的View的。使用如下:
1 2 3 4 | <TextView android:layout_width="match_parent" android:layout_height="match_parent" app:visibleGone="@{isLoading}"/> |
kotlin的方式:
1 2 3 4 5 | @BindingAdapter(value = ["isCollect"]) fun ImageView.isCollect(collect: Boolean) { val vectorDrawableCompat = VectorDrawableCompat.create(BaseApp.context.resources, if (collect) R.drawable.ic_collection_true else R.drawable.ic_collection_false, BaseApp.context.theme) this.setImageDrawable(vectorDrawableCompat) } |
kotlin的方式,使用的是函数扩展的方式,给对应的View扩展一个函数,依然使用@BindingAdapter注解定义对应的扩展属性
使用与Java方式一样
二、参考
https://www.jianshu.com/p/bd9016418af2
这篇说的很全面