这篇用来介绍可被观察的数据,用来实现界面当数据改变时自动更新。
可被观察的数据
参考官网:使用可观察的数据对象。基础的可被观察的数据:
- 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<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秒后改变数据的界面:

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

被折叠的 条评论
为什么被折叠?



