Android DataBinding 笔记二

本文是Android DataBinding系列笔记的第二部分,主要探讨可被观察的数据对象,如ObservableBoolean等,以及如何实现数据变化时界面自动更新。通过观察者模式,DataBinding简化了开发工作。此外,还介绍了DataBinding的基本使用方法,包括创建实现BaseObservable的类,并在布局文件中声明。示例代码展示了如何避免监听错误,确保Activity与DataBinding的正确交互。

这篇用来介绍可被观察的数据,用来实现界面当数据改变时自动更新。

可被观察的数据

参考官网:使用可观察的数据对象。基础的可被观察的数据:

  • ObservableBoolean
  • ObservableChar
  • ObservableShort

等等……都是继承自androidx.databinding.BaseObservable,看下核心源码:

public class BaseObservable implements Observable {
    private transient PropertyChangeRegistry mCallbacks;
    ...
    public void notifyChange() {
        synchronized (this) {
            if (mCallbacks == null) {
                return;
            }
        }
        mCallbacks.notifyCallbacks(this, 0, null);
    }
    ...
    public void notifyPropertyChanged(int fieldId) {
        synchronized (this) {
            if (mCallbacks == null) {
                return;
            }
        }
        mCallbacks.notifyCallbacks(this, fieldId, null);
    }
}
public class CallbackRegistry<C, T, A> implements Cloneable {
    ...
    private List<C> mCallbacks = new ArrayList<C>();
    ...
    private void notifyCallbacks(T sender, int arg, A arg2, final int startIndex,
            final int endIndex, final long bits) {
        long bitMask = 1;
        for (int i = startIndex; i < endIndex; i++) {
            if ((bits & bitMask) == 0) {
                mNotifier.onNotifyCallback(mCallbacks.get(i), sender, arg, arg2);
            }
            bitMask <<= 1;
        }
    }
    ...
    public abstract static class NotifierCallback<C, T, A> {
        public abstract void onNotifyCallback(C callback, T sender, int arg, A arg2);
    }
}

就是普通的观察者模式。只是Google自动生成了特别多的代码,大幅减少了我们的工作量。

基本使用方法

首先我们需要有个实现了BaseObservable的类:

class ObservableData() : BaseObservable() {
    @get:Bindable
    var name: String = ""
    set(value) {
        field = value
        notifyPropertyChanged(BR.name)
    }
    @get:Bindable
    var age: Int = 0
    set(value) {
        field = value
        notifyPropertyChanged(BR.age)
    }
    override fun toString(): String = "ObservableData(name='$name', age=$age)"
}

让后将其声明在布局中:

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <data>
        <import type="android.content.Intent"/>
        <variable name="oBoolean" type="androidx.databinding.ObservableBoolean"/>
        <variable name="oByte" type="androidx.databinding.ObservableByte"/>
        <variable name="oChar" type="androidx.databinding.ObservableChar"/>
        <variable name="oShort" type="androidx.databinding.ObservableShort"/>
        <variable name="oInt" type="androidx.databinding.ObservableInt"/>
        <variable name="oLong" type="androidx.databinding.ObservableLong"/>
        <variable name="oFloat" type="androidx.databinding.ObservableFloat"/>
        <variable name="oDouble" type="androidx.databinding.ObservableDouble"/>
        <variable name="oParcelable" type="androidx.databinding.ObservableParcelable&lt;Intent>"/>
        <variable name="oData" type="com.im_hero.databinding.data.ObservableData" />
        <variable name="aty" type="com.im_hero.databinding.ObservableActivity" />
    </data>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".ObservableActivity">
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{oBoolean ? `true` : `false`}" />
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{String.valueOf(oByte)}" />
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{String.valueOf(oChar)}" />
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{String.valueOf(oShort)}" />
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{String.valueOf(oInt)}" />
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{String.valueOf(oLong)}" />
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{String.valueOf(oFloat)}" />
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{String.valueOf(oDouble)}" />
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{String.valueOf(oParcelable.action)}" />
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{oData.name+`: `+oData.age}" />
    </LinearLayout>
</layout>

有一些DataBinding库中自带的一些基础类型实现在其中,就一起测试了一下,需要注意的是不能通过aty.observableBoolean这种方式,因为DataBinding会去监听aty这个对象,而MainActivity是没有实现BaseObservable的!。Activity代码如下:

class ObservableActivity : AppCompatActivity() {
    val observableBoolean: ObservableBoolean = ObservableBoolean()
    val observableByte: ObservableByte = ObservableByte()
    val observableChar: ObservableChar = ObservableChar('a')
    val observableShort: ObservableShort = ObservableShort()
    val observableInt: ObservableInt = ObservableInt()
    val observableLong: ObservableLong = ObservableLong()
    val observableFloat: ObservableFloat = ObservableFloat()
    val observableDouble: ObservableDouble = ObservableDouble()
    val observableParcelable: ObservableParcelable<Intent> = ObservableParcelable<Intent>(Intent("action"))
    val observableData: ObservableData = ObservableData().apply { name = "Jason"; age = 22 }
    lateinit var binding: ActivityObservableBinding
    var handler = Handler(Looper.getMainLooper())
    var changeData = Runnable {
        observableBoolean.set(!observableBoolean.get())
        observableByte.set((observableByte.get() + 1).toByte())
        observableChar.set('b')
        observableShort.set((observableShort.get() + 1).toShort())
        observableInt.set(observableInt.get() + 1)
        observableLong.set(observableLong.get() + 1)
        observableFloat.set(observableFloat.get() + 1)
        observableDouble.set(observableDouble.get() + 1)
        observableParcelable.set(Intent("new ${observableParcelable.get()!!.action}"))
        observableData.age = observableData.age + 1
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.d(TAG, "onCreate: new")
        binding = DataBindingUtil.setContentView(this, R.layout.activity_observable)
        binding.oBoolean = observableBoolean
        binding.oByte = observableByte
        binding.oChar = observableChar
        binding.oShort = observableShort
        binding.oInt = observableInt
        binding.oLong = observableLong
        binding.oFloat = observableFloat
        binding.oDouble = observableDouble
        binding.oParcelable = observableParcelable
        binding.oData = observableData
        handler.postDelayed(changeData, TimeUnit.SECONDS.toMillis(5))
    }
}

启动时界面:
在这里插入图片描述5秒后改变数据的界面:
在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值