使用可观察数据对象ObservableField¶
更新日期 2021-9-1
- 2021-9-1 完善Kotlin内容
- 2021-6-26 创建文档
可观察性是指一个对象将其数据变化通知给其他对象的能力。通过数据绑定库,您可以让对象、字段或集合变为可观察。 任何 plain-old 对象都可用于数据绑定,但修改对象不会自动使界面更新。通过数据绑定,数据对象可在其数据发生更改时通知其他对象,即监听器。可观察类有三种不同类型:对象、字段和集合。
当其中一个可观察数据对象绑定到界面并且该数据对象的属性发生更改时,界面会自动更新。
可观察字段¶
在创建实现 Observable 接口的类时要完成一些操作,但如果您的类只有少数几个属性,则这样操作的意义不大。在这种情况下,您可以使用通用 Observable 类和以下特定于基元的类,将字段设为可观察字段:
可观察字段
- ObservableBoolean
- ObservableByte
- ObservableChar
- ObservableShort
- ObservableInt
- ObservableLong
- ObservableFloat
- ObservableDouble
- ObservableParcelable
可观察字段是具有单个字段的自包含可观察对象。
避免在访问操作期间封箱和开箱。要使用此机制,Java中使用 public final
属性,或在 Kotlin 中创建只读属性,如以下示例所示:
User类
User.java
import androidx.databinding.ObservableField;
import androidx.databinding.ObservableInt;
public class User {
public final ObservableField<String> firstName = new ObservableField<>();
public final ObservableField<String> lastName = new ObservableField<>();
public final ObservableInt age = new ObservableInt();
}
要访问字段值,请使用 set()
和 get()
访问器方法,如下所示:
使用ObservableField¶
使用Observable
的时候,我们在每个set方法里,都调用notifyPropertyChanged
去通知ui。
我们也可以换用ObservableField
来实现动态更新。
新建类SysInfoObs
,里面使用ObservableField<T>
。可以定义多个属性。
新建类
SysInfoObs.java
layout和之前的差不多。引入的variable
改为我们新建的SysInfoObs
类。
layout引入variable
variable
里使用SysInfoObs,部分内容。
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="com.rustfisher.tutorial2020.databinding.DataUtils" />
<variable
name="info"
type="com.rustfisher.tutorial2020.databinding.data.SysInfoObs" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{info.info1}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{info.timeStr}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{DataUtils.formatTime(info.time)}" />
</LinearLayout>
</layout>
使用SysInfoObsKt的xml。部分内容。
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="com.rustfisher.tutorial2020.databinding.DataUtils" />
<variable
name="info"
type="com.rustfisher.tutorial2020.databinding.data.SysInfoObsKt" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{info.info1}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{info.timeStr}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{DataUtils.formatTime(info.time)}" />
</LinearLayout>
</layout>
activity中修改一下使用方式。新建DataBindingAct2
类,持有SysInfoObs
的对象。
activity
DataBindingAct2.java
import android.os.Bundle;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ObservableArrayList;
import androidx.databinding.ObservableArrayMap;
import com.rustfisher.tutorial2020.AbsActivity;
import com.rustfisher.tutorial2020.R;
import com.rustfisher.tutorial2020.databinding.data.SysInfoObs;
import java.util.Timer;
import java.util.TimerTask;
public class DataBindingAct2 extends AbsActivity {
private ActDataBinding2Binding binding;
private SysInfoObs mSysInfo = new SysInfoObs();
private Timer mTimer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.act_data_binding_2);
binding.setInfo(mSysInfo);
mTimer = new Timer();
mTimer.schedule(new TimerTask() {
@Override
public void run() {
mSysInfo.timeStr.set("Time: " + System.currentTimeMillis());
mSysInfo.time.set(System.currentTimeMillis());
}
}, 0, 500);
}
@Override
protected void onDestroy() {
super.onDestroy();
mTimer.cancel();
}
}
这里是完整的DataBindingAct2Kt代码
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import androidx.databinding.ObservableArrayList
import androidx.databinding.ObservableArrayMap
import com.rustfisher.tutorial2020.AbsActivity
import com.rustfisher.tutorial2020.R
import com.rustfisher.tutorial2020.databinding.data.SysInfoObsKt
import java.util.*
/**
* 演示ObservableFile的kt版本
*/
class DataBindingAct2Kt : AbsActivity() {
private val mSysInfo = SysInfoObsKt()
private var mTimer: Timer? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding: ActDataBinding2KtBinding =
DataBindingUtil.setContentView(this, R.layout.act_data_binding_2_kt)
binding.info = mSysInfo
mTimer = Timer()
mTimer!!.schedule(object : TimerTask() {
override fun run() {
mSysInfo.timeStr.set("Time: " + System.currentTimeMillis())
mSysInfo.time.set(System.currentTimeMillis())
}
}, 0, 100)
val user = ObservableArrayMap<String, Any>()
user["firstName"] = "Rust"
user["lastName"] = "Fisher"
user["age"] = 20
binding.user = user
val obList = ObservableArrayList<Any>()
obList.add("Rust")
obList.add("Fisher")
obList.add("Android")
obList.add(2020)
obList.add("Kotlin")
binding.obList = obList
}
override fun onDestroy() {
super.onDestroy()
mTimer!!.cancel()
}
}
要更新数据时,需要调用ObservableField的set
方法。
运行起来就可以看到更新UI的效果了。
可观察集合¶
某些应用使用动态结构来保存数据。可观察集合允许使用键访问这些结构。
当键为引用类型(如 String)时,ObservableArrayMap
类非常有用,如以下示例所示:
ObservableArrayMap的使用
在布局中,可使用字符串键找到Map,如下所示:
<data>
<import type="androidx.databinding.ObservableArrayMap" />
<variable
name="user"
type="ObservableArrayMap<String, Object>" />
</data>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{user.firstName + " " + user.lastName}' />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf(1 + (Integer)user.age)}" />
<
。
使用 ObservableArrayList
类,如下所示:
ObservableArrayList
在layout中进行设置
<data>
<import type="androidx.databinding.ObservableArrayList" />
<variable
name="obList"
type="ObservableArrayList<Object>" />
</data>
<!-- .... -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{obList[0] + " " + obList[1]}' />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{String.valueOf(1 + (Integer)obList[3])}' />
Kotlin版¶
我们用Kotlin来实现上面的例子。主要看以下3个文件。代码逻辑和前面的一致。
- SysInfoObsKt.kt 信息类
- act_data_binding_2_kt.xml layout
- DataBindingAct2Kt.kt 界面Activity
SysInfoObsKt.kt
layout
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="com.rustfisher.tutorial2020.databinding.DataUtils" />
<variable
name="info"
type="com.rustfisher.tutorial2020.databinding.data.SysInfoObsKt" />
<import type="androidx.databinding.ObservableArrayMap" />
<variable
name="user"
type="ObservableArrayMap<String, Object>" />
<import type="androidx.databinding.ObservableArrayList" />
<variable
name="obList"
type="ObservableArrayList<Object>" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ObservableField kt" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{info.info1}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{info.timeStr}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{DataUtils.formatTime(info.time)}" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_margin="8dp"
android:background="#f0f0f0" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{user.firstName + " " + user.lastName}' />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf(1 + (Integer)user.age)}" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_margin="8dp"
android:background="#f0f0f0" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{obList[0] + " " + obList[1]}' />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{String.valueOf(1 + (Integer)obList[3])}' />
</LinearLayout>
</layout>
Activity界面代码
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import androidx.databinding.ObservableArrayList
import androidx.databinding.ObservableArrayMap
import com.rustfisher.tutorial2020.AbsActivity
import com.rustfisher.tutorial2020.R
import com.rustfisher.tutorial2020.databinding.data.SysInfoObsKt
import java.util.*
/**
* 演示ObservableFile的kt版本
*/
class DataBindingAct2Kt : AbsActivity() {
private val mSysInfo = SysInfoObsKt()
private var mTimer: Timer? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding: ActDataBinding2KtBinding =
DataBindingUtil.setContentView(this, R.layout.act_data_binding_2_kt)
binding.info = mSysInfo
mTimer = Timer()
mTimer!!.schedule(object : TimerTask() {
override fun run() {
mSysInfo.timeStr.set("Time: " + System.currentTimeMillis())
mSysInfo.time.set(System.currentTimeMillis())
}
}, 0, 100)
val user = ObservableArrayMap<String, Any>()
user["firstName"] = "Rust"
user["lastName"] = "Fisher"
user["age"] = 20
binding.user = user
val obList = ObservableArrayList<Any>()
obList.add("Rust")
obList.add("Fisher")
obList.add("Android")
obList.add(2020)
obList.add("Kotlin")
binding.obList = obList
}
override fun onDestroy() {
super.onDestroy()
mTimer!!.cancel()
}
}
本站说明
一起在知识的海洋里呛水吧。广告内容与本站无关。如果喜欢本站内容,欢迎投喂作者,谢谢支持服务器。如有疑问和建议,欢迎在下方评论~