美文网首页
Jetpack 之 DataBinding 小白入手

Jetpack 之 DataBinding 小白入手

作者: 鹅鹅鹅曲项向天歌呀 | 来源:发表于2021-06-30 22:03 被阅读0次

声明 : https://www.jianshu.com/p/714062a9af75
目录:

简介
原理
使用方法

1,一节界面数据绑定(基础使用)
2,二级界面的绑定
3,响应事件
4,BindAdapter
5,RecycleView 绑定机制
6,双向绑定

🌼 简介:

  DataBinding 是一种库,借助该库,可以使用声明性格式(而非程序化地)将布局中的界面组件绑定到应用中的数据源。简单来说,就是帮我们实现 view 和 data 绑定的工具.DataBinding 的出现让布局文件承担了部分原本属于界面的工作,使页面与布局之间的耦合度进一步降低.
  🌷:项目简洁,可读性高,部分与 ui 控件的代码都在布局文件里完成.
  🌷:不再需要 findViewById()
  🌷:布局文件可以包含简单的业务逻辑.ui 控件能够直接与数据模型中的字段绑定,甚至能响应用户的交互.

🌼 原理:

  先略过去吧....太复杂了....🤓🤓🤓,就看看下面的使用方法吧.....

🌼 使用方法:

🍀 一级界面数据绑定
1,build.gradle
android {
    //....
    dataBinding {
        enabled = true
    }
}

  启动绑定数据

2,创建 Person 对象
class Person(var name: String?, var age: Int, var sex: String?)
3,修改布局文件 activity_data_binding.xml

  在布局文件外层加入<layout>标签,可以手动添加,也可以将鼠标移到文件的根目录,单击小灯泡的下来三角框,选中 Convert to data binding layout,AS会自动生成代码.

image.png
<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 的标签,并将命名空间 xmlns 从ConstraintLayout移到了<layout>标签中.这样做的目的是,告诉 DataBinding 库,我们要对该布局进行绑定,此时,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,将数据传递到布局文件

  为了减轻 Activity 的工作量,让布局文件也承担一部分工作,所以要将 Person 对象传递到布局文件.具体做法如下
🐳 首先在布局文件<data>标签中定义个布局变量<variable>,指定类型和名字,名字可以随意定义.

    <data>
        <variable
            name="personD"
            type="com.mcy.test.model.Person" />
    </data>

  <data>标签 用于放置 ui 控件所需要的数据,数据类型可以自定义,比如代码中是的 Person 类,也可以是基本类型.

    <data>
        <variable  name="title"  type="String" />
    </data>

🐳🐳 然后在 Activty 中通过 setPersonD()方法,将 Person 对象传递给布局文件中对应的布局变量.

        activityDataBindingBinding.personD = Person("张三", 30, "男")

🐳🐳🐳 绑定布局文件和成员变量

     <EditText
            android:text="@{personD.name}"/>

        <TextView
            android:text="@{personD.sex}"/>

   布局文件用@{} 表达式为控件赋值
🐳🐳🐳🐳在布局文件引用静态类
  有时候我们需要在布局文件中引用一些 java/kotlin 工具类,帮助我们处理简单的逻辑.

class Utils {
    companion object {
        @JvmStatic
        fun getStr(a: Int): String {
            return a.toString()
        }
    }
}

  我们可以再布局文件中通过<import> 标签导入静态工具类

    <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, "男")
    }
}

运行截图:


图一.png
🍀 二级界面的绑定

   在一级界面布局中,设置好布局变量personD之后,便可以接受来自 Activty 的数据,进而将数据和控件进行绑定,不仅如此,布局变量personD同时也是命名空间 xmlns:app 的一个属性,一级界面正是通过命名空间xmlns:app引用布局变量 personD ,将数据对象传递给二级页面.具体代码如下:
二级页面 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>

运行出来的截图和图一是一样的啦,就粘贴过来啦😇😇😇

🍀 响应事件
1,编写一个类,用于接受和响应 Button 的 onClick 事件.

命名为 HandleClickListener可以单独写一个文件,也可以写在 Activity 中,作为内部类.

    inner class HandleClickListener {
        fun showToast(view: View) {
            Toast.makeText(view.context, "哈哈哈", Toast.LENGTH_LONG).show()
        }
    }

⚠️⚠️⚠️**在定义事件方法名称时需要注意:方法的名称可以和原始函数名称不一样,方法参数和返回值必须和原始的回调函数保持一致。不然会报错,比如:clickFirst(View view)必须要有view参数,如果没有会报错.**⚠️⚠️

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
            )
        //监听
        activityDataBindingBinding.handleC = HandleClickListener()
      }
}

运行截图


image.png
🍀 自定义 BindingAdapter

   在 gradle 启动 DataBinding 库的时候,就会为我们生成所需要的各种类,其中包括大量针对 ui 控件的,名为 XXXBindingAdapter 的类,这些类中包含各种静态方法,并且在这些静态方法前都有@BindingAdapter 标签,标签中的别名对应于 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 库以静态方法的形式为 ui 控件的各个属性绑定了响应的代码.若开发人员在 UI控件的属性中使用了表达式,那么当布局文件被渲染时,属性所绑定的方法会被自动调用.

   比如,当 TextView 被渲染时,android:text属性会自动调用 TextViewBindingAdapter.setText()方法.UI控件通过简单的属性设置,便可以在布局文件中调用所绑定的方法.

那么我们就来自定义一个处理图片的 BindAdapter 类:
1, 添加 Glide 库
    implementation 'com.github.bumptech.glide:glide:4.12.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
2, 添加网络权限
 <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中的方法均为静态方法,第 1 个参数是调用者本身,即 ImageView,第 2 个参数是布局文件在调用该方法传递过来的参数.在静态方法前面需要加入@BindingAdapter()标签,并为该方法起一个别名,此处为 imageV.布局文件正式通过别名来调用方法的.

4, 修改布局文件

   在布局文件定义 String ,传递图片地址.

        <variable
            name="internetImageUrl"
            type="String" />

   ImageView调用

<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 中设置布局文件变量
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"
    }
}

运行截图:


image.png

   在上面的示例中,我们做了接受网络图片地址的展示,如果还希望,在接受网络图片的时候,也能接受本地图片资源作为参数,这样,当网络图片地址为空的时候,则显示本地图片资源所制定的图片.根据这个需求,我们优化一下 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标签中,方法参数以 value = ["", ""]的形式存在,变量 requireAll 作用是告诉 DataBinding 库这些参数是否都要赋值,默认是 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 布局文件,分别绑定不同的数据.

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 方法中,设置布局变量
   ⚠️ ItemRecycleBinding 是 DataBinding 为布局文件 item_recycle.xml 生成的对象

4,Activity 添加数据
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)
    }
}

运行截图:


image.png
🍀 双向绑定
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> 关键字将普通对象包装成可观察对象,可以包装基本类型,集合数组类型,自定义类型的数据.当数据发生变化时,界面所用的与之相关的数据会随之刷新.

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}" 采用@={}表达式完成双向绑定
  

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()
        }
    }

}

运行图片


嘿嘿嘿.gif

END

image.png

相关文章

网友评论

      本文标题:Jetpack 之 DataBinding 小白入手

      本文链接:https://www.haomeiwen.com/subject/nlbpjltx.html