聲明 : http://www.itdecent.cn/p/714062a9af75
目錄:
簡介
原理
使用方法1,一節(jié)界面數(shù)據(jù)綁定(基礎(chǔ)使用)
2,二級界面的綁定
3,響應(yīng)事件
4,BindAdapter
5,RecycleView 綁定機制
6,雙向綁定
?? 簡介:
??DataBinding 是一種庫,借助該庫,可以使用聲明性格式(而非程序化地)將布局中的界面組件綁定到應(yīng)用中的數(shù)據(jù)源。簡單來說,就是幫我們實現(xiàn) view 和 data 綁定的工具.DataBinding 的出現(xiàn)讓布局文件承擔(dān)了部分原本屬于界面的工作,使頁面與布局之間的耦合度進(jìn)一步降低.
????:項目簡潔,可讀性高,部分與 ui 控件的代碼都在布局文件里完成.
????:不再需要 findViewById()
????:布局文件可以包含簡單的業(yè)務(wù)邏輯.ui 控件能夠直接與數(shù)據(jù)模型中的字段綁定,甚至能響應(yīng)用戶的交互.
?? 原理:
??先略過去吧....太復(fù)雜了....??????,就看看下面的使用方法吧.....
?? 使用方法:
?? 一級界面數(shù)據(jù)綁定
1,build.gradle
android {
//....
dataBinding {
enabled = true
}
}
??啟動綁定數(shù)據(jù)
2,創(chuàng)建 Person 對象
class Person(var name: String?, var age: Int, var sex: String?)
3,修改布局文件 activity_data_binding.xml
??在布局文件外層加入<layout>標(biāo)簽,可以手動添加,也可以將鼠標(biāo)移到文件的根目錄,單擊小燈泡的下來三角框,選中 Convert to data binding layout,AS會自動生成代碼.

<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DataBindingActivity">
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
??我們所做的修改是在 ui 布局的最外層加上一個 layout 的標(biāo)簽,并將命名空間 xmlns 從ConstraintLayout移到了<layout>標(biāo)簽中.這樣做的目的是,告訴 DataBinding 庫,我們要對該布局進(jìn)行綁定,此時,rebuild 該項目,DataBinding 庫會為我們生成綁定該布局文件所需要的類.
4,實例化布局
??有了 DataBinding 之后,就可以告別 findViewById()了,我們可以通過DataBindingUtil.setContentView()方法實例化布局文件,該方法返回實例化后布局文件對象,名字和布局文件的名字一樣,并在后面加上 Binding.
class DataBindingActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
var activityDataBindingBinding: ActivityDataBindingBinding =
DataBindingUtil.setContentView<ActivityDataBindingBinding>(
this,
R.layout.activity_data_binding
)
}
}
?? 比如,我的布局文件名字叫 activity_data_binding.xml ,布局文件對象叫 ActivityDataBindingBinding.
5,將數(shù)據(jù)傳遞到布局文件
??為了減輕 Activity 的工作量,讓布局文件也承擔(dān)一部分工作,所以要將 Person 對象傳遞到布局文件.具體做法如下
?? 首先在布局文件<data>標(biāo)簽中定義個布局變量<variable>,指定類型和名字,名字可以隨意定義.
<data>
<variable
name="personD"
type="com.mcy.test.model.Person" />
</data>
??<data>標(biāo)簽 用于放置 ui 控件所需要的數(shù)據(jù),數(shù)據(jù)類型可以自定義,比如代碼中是的 Person 類,也可以是基本類型.
<data>
<variable name="title" type="String" />
</data>
???? 然后在 Activty 中通過 setPersonD()方法,將 Person 對象傳遞給布局文件中對應(yīng)的布局變量.
activityDataBindingBinding.personD = Person("張三", 30, "男")
?????? 綁定布局文件和成員變量
<EditText
android:text="@{personD.name}"/>
<TextView
android:text="@{personD.sex}"/>
?? 布局文件用@{} 表達(dá)式為控件賦值
????????在布局文件引用靜態(tài)類
??有時候我們需要在布局文件中引用一些 java/kotlin 工具類,幫助我們處理簡單的邏輯.
class Utils {
companion object {
@JvmStatic
fun getStr(a: Int): String {
return a.toString()
}
}
}
??我們可以再布局文件中通過<import> 標(biāo)簽導(dǎo)入靜態(tài)工具類
<data>
<import type="com.mcy.test.Utils" />
<data>
??接著在控件中使用
<TextView
android:text="@{Utils.getStr(personD.age)}"/>
6,完整的布局和 Activty 文件
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="com.mcy.test.Utils" />
<variable
name="personD"
type="com.mcy.test.model.Person" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DataBindingActivity">
<EditText
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="9dp"
android:text="@{personD.name}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="7dp"
android:text="@{Utils.getStr(personD.age)}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="9dp"
android:text="@{personD.sex}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView2" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
class DataBindingActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
var activityDataBindingBinding: ActivityDataBindingBinding =
DataBindingUtil.setContentView<ActivityDataBindingBinding>(
this,
R.layout.activity_data_binding
)
//單向
activityDataBindingBinding.personD = Person("張三", 30, "男")
}
}
運行截圖:

?? 二級界面的綁定
?? 在一級界面布局中,設(shè)置好布局變量personD之后,便可以接受來自 Activty 的數(shù)據(jù),進(jìn)而將數(shù)據(jù)和控件進(jìn)行綁定,不僅如此,布局變量personD同時也是命名空間 xmlns:app 的一個屬性,一級界面正是通過命名空間xmlns:app引用布局變量 personD ,將數(shù)據(jù)對象傳遞給二級頁面.具體代碼如下:
二級頁面 layout_second.xml
?? 將 sex 的 view 挪到二級頁面去了
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="personD"
type="com.mcy.test.model.Person" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/textView3"
android:text="@{personD.sex}"
......./><!--省略部分代碼 -->
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
一級頁面 activity_data_binding.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<!--省略部分代碼 -->
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DataBindingActivity">
<!--省略部分代碼 -->
<include
android:id="@+id/in_3"
layout="@layout/layout_second"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView2"
app:personD="@{personD}" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
運行出來的截圖和圖一是一樣的啦,就粘貼過來啦??????
?? 響應(yīng)事件
1,編寫一個類,用于接受和響應(yīng) Button 的 onClick 事件.
命名為 HandleClickListener可以單獨寫一個文件,也可以寫在 Activity 中,作為內(nèi)部類.
inner class HandleClickListener {
fun showToast(view: View) {
Toast.makeText(view.context, "哈哈哈", Toast.LENGTH_LONG).show()
}
}
??????**在定義事件方法名稱時需要注意:方法的名稱可以和原始函數(shù)名稱不一樣,方法參數(shù)和返回值必須和原始的回調(diào)函數(shù)保持一致。不然會報錯,比如:clickFirst(View view)必須要有view參數(shù),如果沒有會報錯.**????
2,在布局文件中定義并使用
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="handleC"
type="com.mcy.test.DataBindingActivity.HandleClickListener" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DataBindingActivity">
<!--省略部分代碼 -->
<Button
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="7dp"
android:onClick="@{handleC::showToast}"
android:text="點我"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/in_3" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
?? 也可以用雙冒號android:onClick="@{handleC::showToast}"
3,在 Avtivity 中實例化HandleClickListener類
class DataBindingActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
var activityDataBindingBinding: ActivityDataBindingBinding =
DataBindingUtil.setContentView<ActivityDataBindingBinding>(
this,
R.layout.activity_data_binding
)
//監(jiān)聽
activityDataBindingBinding.handleC = HandleClickListener()
}
}
運行截圖

?? 自定義 BindingAdapter
?? 在 gradle 啟動 DataBinding 庫的時候,就會為我們生成所需要的各種類,其中包括大量針對 ui 控件的,名為 XXXBindingAdapter 的類,這些類中包含各種靜態(tài)方法,并且在這些靜態(tài)方法前都有@BindingAdapter 標(biāo)簽,標(biāo)簽中的別名對應(yīng)于 ui 控件在布局文件中的屬性.
?? 看個例子,TextView的 TextViewBindingAdapter 的部分源碼:
public class TextViewBindingAdapter {
private static final String TAG = "TextViewBindingAdapters";
@SuppressWarnings("unused")
public static final int INTEGER = 0x01;
public static final int SIGNED = 0x03;
public static final int DECIMAL = 0x05;
@BindingAdapter("android:text")
public static void setText(TextView view, CharSequence text) {
final CharSequence oldText = view.getText();
if (text == oldText || (text == null && oldText.length() == 0)) {
return;
}
if (text instanceof Spanned) {
if (text.equals(oldText)) {
return; // No change in the spans, so don't set anything.
}
} else if (!haveContentsChanged(text, oldText)) {
return; // No content changes, so don't set anything.
}
view.setText(text);
}
//........
}
?? Databinding 庫以靜態(tài)方法的形式為 ui 控件的各個屬性綁定了響應(yīng)的代碼.若開發(fā)人員在 UI控件的屬性中使用了表達(dá)式,那么當(dāng)布局文件被渲染時,屬性所綁定的方法會被自動調(diào)用.
?? 比如,當(dāng) TextView 被渲染時,android:text屬性會自動調(diào)用 TextViewBindingAdapter.setText()方法.UI控件通過簡單的屬性設(shè)置,便可以在布局文件中調(diào)用所綁定的方法.
那么我們就來自定義一個處理圖片的 BindAdapter 類:
1, 添加 Glide 庫
implementation 'com.github.bumptech.glide:glide:4.12.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
2, 添加網(wǎng)絡(luò)權(quán)限
<uses-permission android:name="android.permission.INTERNET" />
3, 編寫處理圖片的 BindAdapter 類
class ImageViewBindingAdapter {
companion object{
@JvmStatic
@BindingAdapter("imageV")
fun setImage(image: ImageView, imageUrl: String?) {
if (!TextUtils.isEmpty(imageUrl)) {
Glide.with(image.context).load(imageUrl).into(image)
} else {
image.setImageResource(R.mipmap.ic_launcher)
}
}
}
}
?? BindAdapter中的方法均為靜態(tài)方法,第 1 個參數(shù)是調(diào)用者本身,即 ImageView,第 2 個參數(shù)是布局文件在調(diào)用該方法傳遞過來的參數(shù).在靜態(tài)方法前面需要加入@BindingAdapter()標(biāo)簽,并為該方法起一個別名,此處為 imageV.布局文件正式通過別名來調(diào)用方法的.
4, 修改布局文件
?? 在布局文件定義 String ,傳遞圖片地址.
<variable
name="internetImageUrl"
type="String" />
?? ImageView調(diào)用
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="internetImageUrl"
type="String" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imageView"
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_marginTop="9dp"
app:imageV="@{internetImageUrl}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button4"
tools:srcCompat="@tools:sample/avatars" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
5, Activity 中設(shè)置布局文件變量
class DataBindingActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
var activityDataBindingBinding: ActivityDataBindingBinding =
DataBindingUtil.setContentView<ActivityDataBindingBinding>(
this,
R.layout.activity_data_binding
)
//自定義 adapter
activityDataBindingBinding.internetImageUrl =
"https://dss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3436121203,3749922833&fm=26&gp=0.jpg"
}
}
運行截圖:

?? 在上面的示例中,我們做了接受網(wǎng)絡(luò)圖片地址的展示,如果還希望,在接受網(wǎng)絡(luò)圖片的時候,也能接受本地圖片資源作為參數(shù),這樣,當(dāng)網(wǎng)絡(luò)圖片地址為空的時候,則顯示本地圖片資源所制定的圖片.根據(jù)這個需求,我們優(yōu)化一下 BindAdapter
class ImageViewBindingAdapter {
companion object {
@JvmStatic
@BindingAdapter(value = ["imageV", "defaultRes"], requireAll = false)
fun setImage(image: ImageView, imageUrl: String?, imageResource: Int) {
if (!TextUtils.isEmpty(imageUrl)) {
Glide.with(image.context).load(imageUrl).into(image)
} else {
image.setImageResource(imageResource)
}
}
}
}
?? 在@BindingAdapter標(biāo)簽中,方法參數(shù)以 value = ["", ""]的形式存在,變量 requireAll 作用是告訴 DataBinding 庫這些參數(shù)是否都要賦值,默認(rèn)是 true.
資源文件:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="internetImageUrl"
type="String" />
<variable
name="imageRes"
type="int" />
</data>
<!--省略部分代碼 ConstraintLayout -->
<ImageView
app:defaultRes="@{imageRes}"
app:imageV="@{internetImageUrl}" />
<!--省略部分代碼 ConstraintLayout -->
</layout>
Activity:
class DataBindingActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
var activityDataBindingBinding: ActivityDataBindingBinding =
DataBindingUtil.setContentView<ActivityDataBindingBinding>(
this,
R.layout.activity_data_binding
)
//自定義 adapter
activityDataBindingBinding.internetImageUrl =
"https://dss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3436121203,3749922833&fm=26&gp=0.jpg"
activityDataBindingBinding.imageRes = R.mipmap.ic_launcher
}
}
?? RecycleView 綁定機制
1,布局文件
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DataBindingActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycle"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
?? RecycleView 的布局
2,item 布局 item_recycle.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="com.mcy.test.Utils" />
<variable
name="personI"
type="com.mcy.test.model.Person" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{personI.name}"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/textView5"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{Utils.getStr(personI.age)}"
app:layout_constraintLeft_toRightOf="@+id/textView4"
app:layout_constraintRight_toLeftOf="@+id/textView6"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{personI.sex}"
app:layout_constraintLeft_toRightOf="@+id/textView5"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
?? RecycleView 的 item 布局文件,分別綁定不同的數(shù)據(jù).
3,編寫 Adapter
class RecycleViewAdapter(private val list: MutableList<Person>) :
RecyclerView.Adapter<MyViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
return MyViewHolder(DataBindingUtil.inflate(
LayoutInflater.from(parent.context), R.layout.item_recycle,parent, false ))
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val personViewModel = list[position]
holder.itemRecycleBinding.personI = personViewModel
}
override fun getItemCount(): Int {
return list.size
}
inner class MyViewHolder(var itemRecycleBinding: ItemRecycleBinding)
: RecyclerView.ViewHolder(itemRecycleBinding.root) //.root 返回的是布局的最外層 ui 視圖
}
?? 編寫 Adapter 需要注意三個地方:
?? ?? 在 onCreateViewHolder()方法中,通過 DataBindingUtil.inflate()實例化布局.
?? ??在 onBindViewHolder 方法中,設(shè)置布局變量
?? ?? ItemRecycleBinding 是 DataBinding 為布局文件 item_recycle.xml 生成的對象
4,Activity 添加數(shù)據(jù)
class DataBindingActivity : AppCompatActivity() {
private val list = mutableListOf<Person>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
var activityDataBindingBinding: ActivityDataBindingBinding =
DataBindingUtil.setContentView<ActivityDataBindingBinding>(
this,
R.layout.activity_data_binding
)
//recycleview
for (i in 1..100) {
var personViewModel1 = Person("張三$i", i, "女")
list.add(personViewModel1)
}
activityDataBindingBinding.recycle.layoutManager = LinearLayoutManager(this)
activityDataBindingBinding.recycle.adapter = RecycleViewAdapter(list)
}
}
運行截圖:

?? 雙向綁定
1,編寫PersonViewModel類
class PersonViewModel(name: String, age: Int, sex: String) {
var name = ObservableField<String>()
var age = ObservableField<Int>()
var sex = ObservableField<String>()
init {
this.name.set(name)
this.age.set(age)
this.sex.set(sex)
}
}
?? ObservableField<T> 關(guān)鍵字將普通對象包裝成可觀察對象,可以包裝基本類型,集合數(shù)組類型,自定義類型的數(shù)據(jù).當(dāng)數(shù)據(jù)發(fā)生變化時,界面所用的與之相關(guān)的數(shù)據(jù)會隨之刷新.
2,編寫布局文件
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<!--省略部分代碼 ConstraintLayout -->
<variable
name="handleC"
type="com.mcy.test.DataBindingActivity.HandleClickListener" />
<variable
name="personVM"
type="com.mcy.test.model.PersonViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DataBindingActivity">
<EditText
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="9dp"
android:text="@={personVM.name}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="7dp"
android:onClick="@{handleC::showToast}"
android:text="@{personVM.name}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/in_3" />
<!--省略部分代碼 ConstraintLayout -->
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
?? android:text="@={personVM.name}" 采用@={}表達(dá)式完成雙向綁定
??
3,編寫 Activty
class DataBindingActivity : AppCompatActivity() {
var personViewModel = PersonViewModel("張三",20,"女")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
var activityDataBindingBinding: ActivityDataBindingBinding =
DataBindingUtil.setContentView<ActivityDataBindingBinding>(
this,
R.layout.activity_data_binding
)
//雙向
activityDataBindingBinding.personVM = personViewModel
}
inner class HandleClickListener {
fun showToast(view: View) {
Toast.makeText(view.context, personViewModel.name.get(), Toast.LENGTH_LONG).show()
}
}
}
運行圖片

END
