安卓---DataBinding的使用(二)

DataBinding 单向绑定

前言

BaseObservable

ObservableField

ObservableCollection


前言

在学习DataBinding后,我们使用它绑定控件后,每次改变数值,都要向DataBinding传值进行更新后才能刷新UI,这时我们就要使用单向绑定实现自动刷新UI。


  • 使用单向绑定刷新UI的方式有三种

    • BaseObservable
    • ObservableField
    • ObservableCollection

BaseObservable

BaseObservable提供了两个刷新UI的方法,分别是

  • notifyPropertyChanged() 和 notifyChange() 。

notifyPropertyChanged(); 只会刷新属于它的UI,对应BR的数据

notifyChange(); 会刷新所有UI。

  • 自定义类继承BaseObservable
  • 在Getter上添加注解@Bindable,以便在BR中的调用
  • 在Setter里面调用notifyPropertyChanged
public class Good extends BaseObservable {
    public String name;

    private String detail;

    private float price;

    public Good(String name,String detail,float price) {
        this.detail = detail;
        this.name = name;
        this.price = price;
    }
    public float getPrice() {
        return price;
    }
    @Bindable
    public String getDetail() {
        return detail;
    }
    @Bindable
    public String getName() {
        return name;
    }
  
    public void setDetail(String detail) {
        this.detail = detail;
        notifyChange();
    }

    public void setName(String name) {
        this.name = name;
        //此处可以简写为BR.name但是name会标红,不会出现编译错误
        notifyPropertyChanged(com.example.mvvmthree.BR.name);
    }

    public void setPrice(float price) {
        this.price = price;

    }
}

在MainActivity中定义改变类,说明改变规则,为了更好的理解notifyPropertyChanged() 和 notifyChange() 的区别,在改变规则中我都加了对price的改变
在这里插入图片描述
对layout布局中在onClick中规定改变规则,格式为@{ }
layout具体实现如下:android:textAllCaps = false 只是为了使显示的文字小写

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <import type="com.example.mvvmthree.Good" />
        <import type="com.example.mvvmthree.MainActivity.GoodHandler" />
        <variable
            name="good"
            type="Good" />
        <variable
            name="goodsHandler"
            type="GoodHandler" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:padding="20dp"
        tools:context=".MainActivity">
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{good.name}"/>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{good.detail}"/>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{String.valueOf(good.price)}"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{()->goodsHandler.changeGoodName()}"
            android:text="改变属性 name 和 price"
            android:textAllCaps="false" />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{()->goodsHandler.changeGoodDetail()}"
            android:text="改变属性 details 和 price"
            android:textAllCaps="false" />
    </LinearLayout>
</layout>

和上一节DataBinding(一)所学相似,初始化对象赋值即可
在这里插入图片描述
在这里插入图片描述
当我们点击改变属性name 和price按钮时,只由name发生了改变,而点击另一个按钮时,两个属性都发生了改变,这就是notifyPropertyChanged() 和 notifyChange() 的区别的体现。


我们可以通过addOnPropertyChangedCallback方法查看哪些数据发生了改变

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main);
        good = new Good("火龙果","好吃不贵",24);
        mainBinding.setGood(good);
        mainBinding.setGoodsHandler(new GoodHandler());
        good.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
            @Override
            public void onPropertyChanged(Observable sender, int propertyId) {
                if (propertyId == com.example.mvvmthree.BR.name) {
                    Log.e("MAIN", "BR.name");
                } else if (propertyId == com.example.mvvmthree.BR.detail) {
                    Log.e("MAIN", "BR.details");
                } else if (propertyId == com.example.mvvmthree.BR._all) {
                    Log.e("MAIN", "BR._all");
                } else {
                    Log.e("MAIN", "未知");
                }
            }
        });
    }

查看代码

ObservableField

ObservableField实际上是对BaseObservable的进一步封装,可以不需要再使用注解,与BaseObservable的用法相差不大,只是再自定义类的创建以及使用时有所不同,再自定义类中的变量类型改为如下形式:

ObservableBoolean

ObservableByte

ObservableChar

ObservableShort

ObservableInt

ObservableLong

ObservableFloat

ObservableDouble

ObservableField< 泛型>

注意:在ObservableField提供了get、set方法,可以拿到值和更新值来达到更新UI效果,一般在类中的变量多用public final修饰,无法书写Set方法,而且即便是写了Set方法也无法对值进行修改,只有通过ObservableField提供的set方法才能修改值。

public class ObservableGood {
    private ObservableField<String> name;
    private ObservableField<String> details;
    private ObservableFloat prices;
    public ObservableGood(ObservableField<String> name,ObservableField<String> details,ObservableFloat prices) {
        this.details = details;
        this.name = name;
        this.prices = prices;
    }

    public ObservableField<String> getDetails() {
        return details;
    }

    public ObservableFloat getPrices() {
        return prices;
    }

    public ObservableField<String> getName() {
        return name;
    }
 }

同样定义变化类
在这里插入图片描述

在此时定义的变化类内部的方法会使对应数据和布局发生改变。

layout的具体实现:

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <data>
        <import type="com.example.databiningtext.MainActivity.Listener" />
        <import type="com.example.databiningtext.ObservableGood"
            alias="Good"/>
        <variable
            name="good"
            type="Good" />
        <variable
            name="listener"
            type="Listener" />
    </data>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity"
        android:orientation="vertical">
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:textSize="20dp"
            android:text="@{good.name}"/>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:textSize="20dp"
            android:text="@{good.details}"/>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:textSize="20dp"
            android:text="@{String.valueOf(good.prices)}"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="改变价格和细节"
            android:layout_gravity="center"
            android:onClick="@{()->listener.changePrice()}"
            android:textAllCaps="false"
            />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="改变名字和细节"
            android:layout_gravity="center" 
            android:onClick="@{()->listener.changeName()}"
            android:textAllCaps="false"/>

    </LinearLayout>

</layout>

最后同样进行初始化和赋值即可

public class MainActivity extends AppCompatActivity {
    private ObservableGood good;
    private ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        good = new ObservableGood(new ObservableField<String>("jerry"),new ObservableField<String>("beta"),new ObservableFloat(90));
        binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
        binding.setGood(good);
        binding.setListener(new Listener());
    }
	···
}

在这里插入图片描述
查看代码


ObservableCollection

当我们的使用对象改为Map或者List形式时,DataBinding提供了 ObservableMap 和 ObservableList可供使用,我们可以直接导入包,直接使用。
(1)ObservableList的使用
首先应引入,并声明数据类型
在写布局时,应注意此时Text View中Text属性使用单引号。

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <import type="androidx.databinding.ObservableList"/>
        <variable
            name="list"
            type="ObservableList&lt;String&gt;" />
    </data>

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text= '@{list[0]}'/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{list[1]}'/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{list[2]}'/>
    </LinearLayout>
</layout>

初始化List,并显示布局
在这里插入图片描述
更新UI的方法与上面介绍的方法相同:声明新的变化类,并引用

public class MainActivity extends AppCompatActivity {
    private ActivityMainBinding binding;
    private ObservableList<String> list;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
        list = new ObservableArrayList<>();
        list.add("study");
        list.add("work");
        list.add("up");
        binding.setList(list);
        binding.setUpdata(new Updata());
    }
    public class Updata{
        public void change() {
            for (int i = 0;i < list.size();i ++) {
                list.set(i,"以改变" + i);
            }
        }
    }
}


在layout中引用:注意ObservableList类型的书写,ObservableList &lt; 元素类型 &gt;

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <import type="androidx.databinding.ObservableList"/>
        <import type="com.example.databindingtext5.MainActivity.Updata"/>
            <!-- 注意ObservableList类型的书写,ObservableList &lt; 元素类型 &gt;-->
        <variable
            name="list"
            type="ObservableList&lt;String&gt;" />
        <variable
            name="updata"
            type="Updata" />
    </data>

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="@{list[0]}"/>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="@{list[1]}"/>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="@{list[2]}"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:onClick="@{()->updata.change()}"
            android:text="改变"/>


    </LinearLayout>
</layout>

效果图:
在这里插入图片描述
查看代码
( 2 )ObservableMap的使用

  • 布局文件添加ObservableMap的包:androidx.databinding.ObservableMap,与上面的ObservableList的类型书写形式相似:ObservableMap &lt; key类型,对应数据类型&gt;
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <import type="androidx.databinding.ObservableMap"/>
        <variable
            name="people"
            type="ObservableMap&lt;String,Object&gt;" />
    </data>

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{String.valueOf(people["ss"])}'
             />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{people["yy"]}'/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{people["xx"]}'/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text='@{String.valueOf(people["aa"])}'/>
    </LinearLayout>
</layout>

同样的初始化并赋值
在这里插入图片描述
自动更新UI与上面所学形式相同,此处不在举例。

代码

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要在 Kotlin 中使用 MVVM 模式实现 TextView 中部分文字的字体变大、设置不同颜色以及部分文字设置点击事件,可以按照以下步骤进行: 1. 创建一个 ViewModel 类,例如 `TextViewModel.kt`,用于处理文本相关的逻辑和数据。 ```kotlin import androidx.lifecycle.ViewModel class TextViewModel : ViewModel() { // 在这里处理文本相关的逻辑和数据 } ``` 2. 在 XML 布局文件中定义一个 TextView,并设置相应的属性。 ```xml <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{viewModel.spannableText}" android:textColor="@{viewModel.textColor}" android:onClick="@{viewModel.onTextClick}" /> ``` 3. 创建一个继承自 BaseObservableObservableField 类型的属性,用于在 ViewModel 中绑定数据到 TextView 相关的属性。 ```kotlin import androidx.databinding.BaseObservable import androidx.databinding.Bindable import androidx.databinding.ObservableField class TextViewModel : BaseObservable() { val spannableText = ObservableField<String>() val textColor = ObservableField<Int>() // 在这里处理文本相关的逻辑和数据 fun onTextClick() { // 处理点击事件的逻辑 } } ``` 4. 在 Activity 或 Fragment 中使用 DataBinding 绑定布局,并实例化 ViewModel。 ```kotlin import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import androidx.databinding.DataBindingUtil import com.example.mvvm.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding private lateinit var viewModel: TextViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = DataBindingUtil.setContentView(this, R.layout.activity_main) // 初始化 ViewModel viewModel = TextViewModel() // 绑定 ViewModel binding.viewModel = viewModel } } ``` 现在,您可以在 ViewModel 类中处理文本相关的逻辑和数据,并将结果绑定到 TextView 的相应属性上。同时,您还可以在 ViewModel 中定义点击事件的处理函数,并将其与 TextView 的 onClick 属性绑定。 希望这个示例能帮助您理解如何使用 MVVM 模式在 Kotlin 中实现 TextView 中部分文字的字体变大、设置不同颜色以及部分文字设置点击事件。如果您有任何其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值