AndroidX 库包含架构组件,您可以使用这些组件设计可靠、可测试且可维护的应用。数据绑定库可与架构组件无缝协作,进一步简化界面的开发。应用中的布局可以绑定到架构组件中的数据,这有助于您管理界面控制器的生命周期并向界面通知数据的变化。
本文档介绍了如何将架构组件纳入到应用中,以便充分利用数据绑定库。
使用 LiveData 将数据变化通知给界面
您可以使用 LiveData 对象作为数据绑定来源,自动将数据变化通知给界面。如需详细了解此架构组件,请参阅 LiveData 概览。
与实现 Observable 的对象(如可观察字段)不同,LiveData 对象了解订阅数据更改的观察器的生命周期。这种知识可带来许多优势,使用 LiveData 的优势中对此进行了说明。在 Android Studio 3.1 及更高版本中,您可以在数据绑定代码中将可观察字段替换为 LiveData 对象。
如需将 LiveData 对象与绑定类一起使用,需要指定生命周期所有者,以定义 LiveData 对象的范围。以下示例在绑定类实例化后将 activity 指定为生命周期所有者:
Kotlin
class ViewModelActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// Inflate view and obtain an instance of the binding class.
val binding: UserBinding = DataBindingUtil.setContentView(this, R.layout.user)
// Specify the current activity as the lifecycle owner.
binding.setLifecycleOwner(this)
}
}
Java
class ViewModelActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// Inflate view and obtain an instance of the binding class.
UserBinding binding = DataBindingUtil.setContentView(this, R.layout.user);
// Specify the current activity as the lifecycle owner.
binding.setLifecycleOwner(this);
}
}
您可以使用 ViewModel 组件将数据绑定到布局,如以下部分所述。在 ViewModel 组件中,您可以使用 LiveData 对象来转换数据或合并多个数据源。以下示例展示了如何转换 ViewModel 中的数据:
Kotlin
class ScheduleViewModel : ViewModel() {
val userName: LiveData<String>
init {
val result = Repository.userName
userName = Transformations.map(result) { result -> result.value }
}
}
Java
class ScheduleViewModel extends ViewModel {
LiveData<String> username;
public ScheduleViewModel() {
String result = Repository.userName;
userName = Transformations.map(result, result -> result.value);
}
}
使用 ViewModel 管理界面相关数据
数据绑定库可与 ViewModel 组件无缝协作。ViewModel 会公开布局观察到的数据,并对数据的更改做出响应。
将 ViewModel 组件与数据绑定库结合使用,可让您将界面逻辑从布局中移出,并移入更易于测试的组件中。数据绑定库可确保视图在需要时与数据源绑定和解除绑定。其余大部分工作都是确保您公开正确的数据。如需详细了解此架构组件,请参阅 ViewModel 概览。
如需将 ViewModel 组件与数据绑定库搭配使用,您必须实例化组件(该组件继承自 ViewModel 类),获取绑定类的实例,并将 ViewModel 组件分配给绑定类中的属性。以下示例展示了如何将该组件与库搭配使用:
Kotlin
class ViewModelActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// Obtain the ViewModel component.
val userModel: UserModel by viewModels()
// Inflate view and obtain an instance of the binding class.
val binding: UserBinding = DataBindingUtil.setContentView(this, R.layout.user)
// Assign the component to a property in the binding class.
binding.viewmodel = userModel
}
}
Java
class ViewModelActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// Obtain the ViewModel component.
UserModel userModel = new ViewModelProvider(this).get(UserModel.class);
// Inflate view and obtain an instance of the binding class.
UserBinding binding = DataBindingUtil.setContentView(this, R.layout.user);
// Assign the component to a property in the binding class.
binding.viewmodel = userModel;
}
}
在布局中使用绑定表达式将 ViewModel 组件的属性和方法分配给相应的视图,如下面的示例所示:
<CheckBox
android:id="@+id/rememberMeCheckBox"
android:checked="@{viewmodel.rememberMe}"
android:onCheckedChanged="@{() -> viewmodel.rememberMeChanged()}" />
使用 Observable ViewModel 更好地控制绑定适配器
您可以使用实现 Observable 接口的 ViewModel 组件,将数据变化通知给其他应用组件,这与使用 LiveData 对象的方式类似。
在某些情况下,您可能更愿意使用实现 Observable 接口的 ViewModel 组件,而不是使用 LiveData 对象,即使您会失去 LiveData 的生命周期管理功能。使用实现 Observable 的 ViewModel 组件,您可以更好地控制应用中的绑定适配器。例如,此模式可让您更好地控制数据发生更改时的通知;还可让您指定自定义方法,以便在双向数据绑定中设置属性的值。
如需实现可观察的 ViewModel 组件,您必须创建一个继承自 ViewModel 类并实现 Observable 接口的类。您可以使用 addOnPropertyChangedCallback() 和 removeOnPropertyChangedCallback() 方法,在观察者订阅或取消订阅通知时提供自定义逻辑。您还可以提供在 notifyPropertyChanged() 方法中属性发生更改时运行的自定义逻辑。以下代码示例展示了如何实现可观察的 ViewModel:
Kotlin
/**
* A ViewModel that is also an Observable,
* to be used with the Data Binding Library.
*/
open class ObservableViewModel : ViewModel(), Observable {
private val callbacks: PropertyChangeRegistry = PropertyChangeRegistry()
override fun addOnPropertyChangedCallback(
callback: Observable.OnPropertyChangedCallback) {
callbacks.add(callback)
}
override fun removeOnPropertyChangedCallback(
callback: Observable.OnPropertyChangedCallback) {
callbacks.remove(callback)
}
/**
* Notifies observers that all properties of this instance have changed.
*/
fun notifyChange() {
callbacks.notifyCallbacks(this, 0, null)
}
/**
* Notifies observers that a specific property has changed. The getter for the
* property that changes must be marked with the @Bindable annotation to
* generate a field in the BR class to be used as the fieldId parameter.
*
* @param fieldId The generated BR id for the Bindable field.
*/
fun notifyPropertyChanged(fieldId: Int) {
callbacks.notifyCallbacks(this, fieldId, null)
}
}
Java
/**
* A ViewModel that is also an Observable,
* to be used with the Data Binding Library.
*/
class ObservableViewModel extends ViewModel implements Observable {
private PropertyChangeRegistry callbacks = new PropertyChangeRegistry();
@Override
protected void addOnPropertyChangedCallback(
Observable.OnPropertyChangedCallback callback) {
callbacks.add(callback);
}
@Override
protected void removeOnPropertyChangedCallback(
Observable.OnPropertyChangedCallback callback) {
callbacks.remove(callback);
}
/**
* Notifies observers that all properties of this instance have changed.
*/
void notifyChange() {
callbacks.notifyCallbacks(this, 0, null);
}
/**
* Notifies observers that a specific property has changed. The getter for the
* property that changes must be marked with the @Bindable annotation to
* generate a field in the BR class to be used as the fieldId parameter.
*
* @param fieldId The generated BR id for the Bindable field.
*/
void notifyPropertyChanged(int fieldId) {
callbacks.notifyCallbacks(this, fieldId, null);
}
}
为你推荐
- 注意:当 JavaScript 处于关闭状态时,系统会显示链接文字
- 使用可观察的数据对象
- 加载并显示分页数据
- 将 Kotlin 协程与生命周期感知型组件一起使用