android——databinding中字符串的拼接处理、TextView显示的值随activity的属性值改变同时改变--LiveData、双向绑定过滤器、监听某个值的改变

2023-05-16

简介

使用的技术是观察者与被观察者的模式,在google推荐的案例中也有使用到,现在我把它封装成一个扩展函数,使得使用更加简单明了

注意

1、在build.gradle添加databinding,在android{}节点添加

dataBinding {
        enabled true        
    }

或者(一般用下面的) :

buildFeatures {
        dataBinding = true
        viewBinding true
    }

2、在activity里绑定binding
在这里插入图片描述

在fragment里绑定binding: _binding = FragmentReturnMainBinding.inflate(inflater, container, false)
在这里插入图片描述

1、TextView显示的值随activity的属性值改变同时改变–LiveData

代码

MainActivity

class MainActivity : AppCompatActivity() {


    private val mutableLiveData = MutableLiveData<String>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        tv2.bindValue(mutableLiveData,this)

        bt1.setOnClickListener {
//            第二种使用扩展函数封装好的模式
            mutableLiveData.value="我爱李曼娜"

        }

    }

    /**
     * TextView的扩展函数
     * 使用方法:
     * val mutableLiveData = MutableLiveData<String>()
     * tv2.bindValue(mutableLiveData,this)
     *
     * 在按钮事件里调用:mutableLiveData.value="我爱你"
     * TextView中显示的值就会跟着改变
     */
    fun TextView.bindValue( mutableLiveData:MutableLiveData<String>,lifecycleOwner:LifecycleOwner){
        var text1: LiveData<String> = Transformations.map(mutableLiveData) {
//            "观察者: $it"
            it
        }
        text1.observe(lifecycleOwner, Observer<String> {
            this.text = it
        })

    }


}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <TextView
            android:id="@+id/tv2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!" />

        <Button
            android:id="@+id/bt1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:text="赋值3"/>

    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

2、xml使用layout–data方式双向绑定

功能:点击按钮按钮换背景颜色,字体换颜色,textview换内容,效果图:
在这里插入图片描述
代码:

public class User {
    private String status;
    private String hint;
    private boolean isOnline;

    public User(String status, String hint, boolean isOnline) {
        this.status = status;
        this.hint = hint;
        this.isOnline = isOnline;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getHint() {
        return hint;
    }

    public void setHint(String hint) {
        this.hint = hint;
    }

    public boolean getIsOnline() {
        return isOnline;
    }

    public void setIsOnline(boolean isOnline) {
        this.isOnline = isOnline;
    }
}

MainActivity :

import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import android.os.Bundle;
import android.view.View;

import com.example.databinding.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {
    ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        User user = new User("已下线", "快开启一天的旅程吧!!", false);
        binding.setUser(user);

    }

    public void switchStatus(View view) {
        User user = new User("已上线", "祝您旅途愉快,谢谢!!", true);
        binding.setUser(user);
    }
}
<?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="user"
            type="com.example.databinding.User" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/tvStatus"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.status}"
            app:layout_constraintBottom_toTopOf="@+id/tvHint"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/tvHint"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.hint}"
            app:layout_constraintBottom_toTopOf="@+id/button"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/tvStatus" />

        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@{user.isOnline?@drawable/btn_shape:@drawable/btn_shape_press}"
            android:onClick="switchStatus"
            android:text="状态切换"
            android:textColor="@{user.isOnline?@color/purple_200:@color/teal_200}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/tvHint" />
        <!--        android:background="@{user.isOnline?@color/purple_200:@color/teal_200}"-->

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

btn_shape.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:radius="10dp" />
    <solid android:color="#2196F3" />
</shape>

btn_shape_press.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:radius="10dp" />
    <solid android:color="#FF018786" />
</shape>

主题:<style name="Theme.Databinding" parent="Theme.MaterialComponents.DayNight.NoActionBar.Bridge">

下载地址:https://download.csdn.net/download/wy313622821/33937925

注意:
1.ActivityMainBinding 这里的命名需要与xml的名称对应

3、MVVM双向绑定(过滤器)

<?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="viewModel"
            type="com.abtalk.databinding.MainViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{viewModel.age+`:字符串:`}"
            android:visibility="@{viewModel.visibility}"            
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
        <!--android:visibility="@{viewModel.visibility}"  这里比较复杂的逻辑运算放到mainactivity代码里写-->
       
        <TextView
            android:id="@+id/tv11"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{(viewModel.age>13)?@string/cnr:@string/w_cnr}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="change"
            android:text="改变"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/textView" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

activity代码

class MainActivity : AppCompatActivity() {
    private lateinit var mainViewModel: MainViewModel
    private lateinit var databindng: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        databindng = DataBindingUtil.setContentView(this, R.layout.activity_main)
        mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
        databindng.viewModel = mainViewModel
    }

    fun change(view: View) {
        mainViewModel.age.set(15)
    }
}

MainViewModel

class MainViewModel : ViewModel() {

    val age = ObservableInt(1)
    val visibility = object : ObservableInt(age) {
        override fun get(): Int {
            Log.e("wang", "===>")
            return if (age.get() > 13)
                View.GONE
            else
                View.VISIBLE
        }
    }

}

注意:上面的visibility如果没有在xml里面绑定的话,是不会触发输出的(Log.e(“wang”, “===>”))

String.xml

<resources>
    <string name="app_name">Databinding</string>
    <string name="cnr">成年人</string>
    <string name="w_cnr">未成年人</string>
</resources>

完整的代码地址:https://download.csdn.net/download/wy313622821/86905039

4、dataBinding中TextView中字符串的拼接处理

第一种:

android:text="@{ `字符串:` + str}"/>

第二种:
android:text=‘@{@string/user_name+bean.name}’
这里的引号需要使用单引号

5、监听某个值的改变,并做一些其他的操作

某个值为:
var aa: ObservableField = ObservableField(0)

监听:

 aa.addOnPropertyChangedCallback(object : OnPropertyChangedCallback() {
            override fun onPropertyChanged(observable: Observable?, i: Int) {
                Log.e("wang","===>"+i)
            }
        })

让这个值改变
aa.set(10)
这样就会触发上面的回调接口

6、绑定点击事件

第一步,activity中把xml里的viewmodel跟activity的viewmodel实例进行绑定

private val returnListViewModel by viewModels<ReturnListViewModel>()

//在oncreat中
binding.viewModel = returnListViewModel

// xml代码中
 <variable
            name="viewModel"
            type="***.medicine.module_return.returned.viewmodel.ReturnListViewModel" />

第二步,带参数的点击:@{() -> viewModel.click(1)}

//xml:
android:onClick="@{() -> viewModel.click(1)}"
//ViewModel:
public void click(num:Int){

}

课外知识:可以把xml里的frag跟activity的this实例进行绑定,把绑定点击事件放在fragment里

// xml代码中

<variable
            name="frag"
            type="***.medicine.module_return.returned.viewmodel.Fragment" />
// fragment代码中
binding.frag = this

双向绑定的显示隐藏需要用到View:

就可以使用View.Gone

7、高级用法

android:text='@{username??"null"}' 

如果表达式username为null时,则显示“null”, 不为空显示username的值

<data>
     <!--使用Java某些类都要通过import导入才能正常使用-->
     <import type="android.text.TextUtils" alias="textUtlis" />
</data>
<androidx.appcompat.widget.AppCompatButton
            android:id="@+id/bt_login"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:enabled="@{!textUtlis.isEmpty(username)?!textUtlis.isEmpty(password)?true:false:false}"
            android:onClick='@{v->loginModel.login(username ?? "",password ?? "",v) }'
            android:text="登陆" />

使用 && 进行多条件判断
我们都希望可以在databinding layout表达式中直接使用&& 逻辑判断,但遗憾会报错!这里可以使用&的转义字符 & 替代,则上面的用户名密码判空操作可以直接写成

android:enabled="@{!TextUtlis.isEmpty(username) &amp; &amp;  !TextUtlis.isEmpty(password)}"
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

android——databinding中字符串的拼接处理、TextView显示的值随activity的属性值改变同时改变--LiveData、双向绑定过滤器、监听某个值的改变 的相关文章

  • 35(牛客Top100)-84.柱状图中最大的矩形

    给定 n 个非负整数 xff0c 用来表示柱状图中各个柱子的高度 每个柱子彼此相邻 xff0c 且宽度为 1 求在该柱状图中 xff0c 能够勾勒出来的矩形的最大面积 思路 xff1a 方法1 xff1a 栈 43 邵兵 span clas
  • 36(牛客Top100)-85.最大矩阵

    给定一个仅包含 0 和 1 大小为 rows x cols 的二维二进制矩阵 xff0c 找出只包含 1 的最大矩形 xff0c 并返回其面积 思路 xff1a 先抄下来 xff0c 我也不懂 方法1 xff1a 单调栈 span clas
  • 新建springboot项目

    1 新建项目 xff0c 选择Spring Initializr 2 直接finish xff0c 然后就等待下载各种包 xff0c 大约10分钟左右 3 包变绿后 xff0c pom xml中导入web依赖 span class toke
  • springboot整合mybatis实现增删改查

    1 新建springboot项目 xff0c 连接数据库 2 导入依赖 span class token generics span class token punctuation lt span dependencies span cla
  • 37(牛客Top100)-94.二叉树的中序遍历

    给定一个二叉树的根节点 root xff0c 返回它的 中序 遍历 思路 xff1a 方法1 xff1a 递归 按照访问左子树 根节点 右子树的方式遍历这棵树 span class token keyword public span spa
  • 38(牛客Top100)-96.不同的二叉搜索树

    给你一个整数 n xff0c 求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种 xff1f 返回满足题意的二叉搜索树的种数 思路 xff1a 1 动态规划 动态方程 xff1a span class token
  • 40(牛客Top100)-101.对称二叉树

    给定一个二叉树 xff0c 检查它是否是镜像对称的 思路 xff1a 方法1 xff1a 递归 span class token keyword public span span class token keyword boolean sp
  • 39(牛客Top100)-98.验证二叉搜索树

    给你一个二叉树的根节点 root xff0c 判断其是否是一个有效的二叉搜索树 有效 二叉搜索树定义如下 xff1a 节点的左子树只包含 小于 当前节点的数 节点的右子树只包含 大于 当前节点的数 所有左子树和右子树自身必须也是二叉搜索树
  • Excel合并计算完成多表格数据汇总求和

    Excel合并计算完成多表格数据汇总求和 多表格数据汇总可以使用透视表 xff0c 使用函数 xff0c 今天读书屋OFFICE网陈飞老师分享一个通过合并计算完成多表格数据汇总方法 xff0c 合并计算分为两种情况 xff0c 一种情况是
  • Google Datastore 学习记录

    由于在google app engine 使用google cloud sql 是要收费的 xff0c 于是学习一下google提供的免费的非关系型数据库datastore 它的特点有 xff1a No planned downtime x
  • 41(牛客Top100)-104.二叉树的最大深度

    给定一个二叉树 xff0c 找出其最大深度 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数 说明 叶子节点是指没有子节点的节点 思路 xff1a 方法1 xff1a 深度优先搜索 span class token keyword p
  • 42(牛客Top100)-102.二叉树的层序遍历

    给你一个二叉树 xff0c 请你返回其按 层序遍历 得到的节点值 xff08 即逐层地 xff0c 从左到右访问所有节点 xff09 思路 xff1a 用队列按层次遍历 方法1 xff1a 广度优先搜索 span class token k
  • MySQL总结

    1 数据库基础知识 1 1 什么是MySQL MySQL是一个关系型数据库管理系统 xff0c MySQL是最好的 RDBMS Relational Database Management System xff0c 关系数据库管理系统 应用
  • 45(牛客Top100)-121.买卖股票的最优时间

    给定一个数组 prices xff0c 它的第 i 个元素 prices i 表示一支给定股票第 i 天的价格 你只能选择 某一天 买入这只股票 xff0c 并选择在 未来的某一个不同的日子 卖出该股票 设计一个算法来计算你所能获取的最大利
  • 47(牛客Top100)-128.最长连续子序列

    给定一个未排序的整数数组 nums xff0c 找出数字连续的最长序列 xff08 不要求序列元素在原数组中连续 xff09 的长度 请你设计并实现时间复杂度为 O n 的算法解决此问题 思路 xff1a 方法1 xff1a 利用set集合
  • 48(牛客Top100)-136.只出现一次的数字

    给定一个非空整数数组 xff0c 除了某个元素只出现一次以外 xff0c 其余每个元素均出现两次 找出那个只出现了一次的元素 说明 xff1a 你的算法应该具有线性时间复杂度 你可以不使用额外空间来实现吗 xff1f 思路 xff1a 方法
  • stc-isp 51单片机烧录软件的安装

    stc isp的获取 百度网盘链接 xff1a https pan baidu com s 1vDTN2o8ffvczzNQGfyjHng 提取码 xff1a gdzf stc isp安装 此软件是绿色软件 xff0c 双击直接运行即可 开
  • 实习日记。。。

    第一周 第一天7 11 周一 入职第一天 xff0c 一直在数据库建表 xff0c 写了二十来个 xff0c 还有领了工卡和饭卡 xff0c 带我的老大哥请我恰了一顿 xff0c 晚上下班的时候 xff0c 因为舍不得我的电脑所以多待了一个
  • TCP/IP协议栈Lwip的设计与实现:之三

    接上文 xff1a TCP IP协议栈Lwip的设计与实现 xff1a 之二 龙赤子的博客 CSDN博客 目录 10 xff0e TCP处理 10 1概述 10 2数据结构 10 3序列号计算 10 4数据入队和传输 10 5接收段数据 1
  • c++——Unicode编码和多字节编码的区别

    1 VS项目属性不同字符集的区别 单字节字符集 xff1a 顾名思义 xff0c 单字节字符集就是用一个字节表示一个字符 xff0c 简称SBCS ASCII就是单字节字符集 在编码的过程中char类型就是单字节编码 Unicode字符集

随机推荐

  • 蓝桥杯 例题 切割矩形

    include lt bits stdc 43 43 h gt using namespace std int ans 61 0 int f int a int b ans 43 43 if a 61 61 1 amp amp b 61 6
  • c++——Unicode、UTF-8、UTF-16

    计算机起源于美国 xff0c 上个世纪 xff0c 他们对英语字符与二进制位之间的关系做了统一规定 xff0c 并制定了一套字符编码规则 xff0c 这套编码规则被称为ASCII编码 ASCII 编码一共定义了128个字符的编码规则 xff
  • spark MLlib之分类和回归

    MLlib支持多种方法用来处理二分分类 xff0c 多类分类以及回归分析 xff0c 下表列出了问题及对应的处理方法 xff1a 问题类型 支持的方法 二分分类 现行SVM xff0c 逻辑回归 xff0c 决策树 xff0c 贝叶斯 多类
  • 生产者消费者模型详解以及实现

    生产者消费者模式 我们先来看看什么是生产者消费者模式 xff0c 生产者消费者模式是程序设计中非常常见的一种设计模式 xff0c 被广泛运用在解耦 消息队列等场景 在现实世界中 xff0c 我们把生产商品的一方称为生产者 xff0c 把消费
  • 高频面试点:静态链接库与动态链接库

    库是写好的现有的 xff0c 成熟的 xff0c 可以复用的代码 现实中每个程序都要依赖很多基础的底层库 xff0c 不可能每个人的代码都从零开始 xff0c 因此库的存在意义非同寻常 本质上来说库是一种可执行代码的二进制形式 xff0c
  • cordova打包app热更新问题

    定义 xff1a 基于 cordova 框架能将web应用 js html css 图片等 打包成 App 当 App 在终端上安装后 xff0c 不需要重新下载app xff0c 实现内壳更新 原理 xff1a 1 在项目根目录的conf
  • 一文解决 Python读取文件的全部知识

    文件是无处不在的 xff0c 无论我们使用哪种编程语言 xff0c 处理文件对于每个程序员都是必不可少的 文件处理是一种用于创建文件 写入数据和从中读取数据的过程 xff0c Python 拥有丰富的用于处理不同文件类型的包 xff0c 从
  • 总结实验室对转录组及lncRNA数据分析的思路

    继师兄详细地讲述这个思路之后 xff0c 我进行一个归纳总结 xff08 师兄说 xff0c 首先要建立一个思想上的流程 xff0c 再来纠结软件 命令这些细节 xff01 xff01 xff01 xff01 xff01 xff01 xff
  • Android 高通7.1系统默认横屏显示(无G-sensor)

    竖屏横用 xff0c logo用的还是竖屏资源 1 添加宏控制 device qcom msm8909 system prop span class token comment add start span persist span cla
  • Android11 授权应用获取IMEI号和ICCID

    在Android11上获取IMEI号等设备信息需要android permission READ PRIVILEGED PHONE STATE权限 xff0c 而这个权限又只授予系统级应用 项目中如果targetSdkVersion值小于2
  • Enum枚举前后端传输展示方案

    1 定义枚举类型 public enum RolesTypeEnum implements Enumerator MANAGER 34 管理员 34 0 BUSINESS 34 招商员工 34 1 PROPERTY 34 物业员工 34 2
  • 蓝桥杯2018年第九届真题-递增三元组-题解(C语言代码)

    include lt bits stdc 43 43 h gt using namespace std const int MAXN 61 100005 int a MAXN b MAXN c MAXN int n sum int main
  • Altium Designer 推挤布线

    在进入交互式布线模式时按 TAB 键进入属性对话框 xff0c 在 Current Mode 参数项中选择Push Obstacles 模式 xff0c 然后点击 OK 退出设置这时将进入挤推布线模式 xff0c 它可以帮你自动移开遮挡的导
  • 范数及其意义

    什么是范数 xff1f 范数 Norm 是具有度量性质的函数 xff0c 它经常使用来衡量矢量函数的长度或大小 xff0c 是泛函分析中的一个基本概念 要更好的理解范数 xff0c 就要从函数 几何与矩阵的角度去理解 xff0c 我们都知道
  • cmd的炫酷玩法教程

    在我们看电影的时候 xff0c 经常看到黑客在电脑是一顿猛如虎的操作 然后电脑上就出现一系列花里胡哨的画面 xff0c 其实那种画面我们用cmd的一行代码就能搞定 第一步 按Win 43 R xff0c 输入cmd xff0c 打开小黑框
  • Java里面关于currentTimeMilllis()方法

    关于currentTimeMillis 方法的一些说明 很多的朋友在刚开始接触long这个数据类型的时候 xff0c 就会被引导去接触一个叫做currentTimeMillis 的方法 xff0c 看名字貌似很复杂的样子 xff0c 其实很
  • ubuntu安装nodejs的正确方式

    sudo apt get remove nodejs sudo apt get remove npm curl o https raw githubusercontent com nvm sh nvm v0 39 2 install sh
  • Android Studio 3.+ 使用gradle配置动态修改包名、图标、常量等,实现动态配置编译不同包名的APP和多渠道打包

    Android Studio 3 1 3 43 gradle 4 4 43 build gradle 3 1 3 示例代码已上传github https github com weixx gradle package 配置差别化渠道包 ap
  • 抽奖助手自动参与抽奖

    无码科技开发了一个抽奖的小程序 xff0c 里面有一些赞助商提供的抽奖 xff0c 但是每次都要一个一个的点才能参与 xff0c 很麻烦 参考了网上的一些教程 xff0c 写了一个脚本 xff0c 可以不用一个一个地点就可以参与抽奖 过程的
  • android——databinding中字符串的拼接处理、TextView显示的值随activity的属性值改变同时改变--LiveData、双向绑定过滤器、监听某个值的改变

    简介 使用的技术是观察者与被观察者的模式 xff0c 在google推荐的案例中也有使用到 xff0c 现在我把它封装成一个扩展函数 xff0c 使得使用更加简单明了 注意 1 在build gradle添加databinding xff0