将布局视图绑定到架构组件

AndroidX 库包含架构组件,您可以使用它来设计健壮、可测试和可维护的应用。数据绑定库与架构组件无缝协作,以进一步简化 UI 开发。应用中的布局可以绑定到架构组件中的数据,这有助于您管理 UI 控制器的生命周期并通知 UI 数据的变化。

此页面显示如何将架构组件整合到您的应用中,以充分利用数据绑定库。

使用 LiveData 通知 UI 数据变化

您可以使用LiveData对象作为数据绑定源,以自动通知 UI 数据的变化。有关此架构组件的更多信息,请参阅LiveData 概述

与实现Observable的对象(例如可观察字段)不同,LiveData对象了解订阅数据更改的观察者的生命周期。此知识带来了许多好处,在使用 LiveData 的优势中进行了说明。在 Android Studio 3.1 及更高版本中,您可以使用LiveData对象替换数据绑定代码中的可观察字段。

要在绑定类中使用LiveData对象,您需要指定一个生命周期所有者来定义LiveData对象的范围。以下示例在绑定类实例化后指定活动作为生命周期所有者

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

    init {
        val result = Repository.userName
        userName = Transformations.map(result) { result -> result.value }
    }
}

Java

class ScheduleViewModel extends ViewModel {
    LiveData username;

    public ScheduleViewModel() {
        String result = Repository.userName;
        userName = Transformations.map(result, result -> result.value);
    }
}

使用 ViewModel 管理 UI 相关数据

数据绑定库与ViewModel组件无缝协作。ViewModel公开布局观察并对其更改做出反应的数据。将ViewModel组件与数据绑定库一起使用,可以让您将UI逻辑从布局移到组件中,这些组件更容易测试。数据绑定库确保在需要时将视图绑定和解除绑定到数据源。其余的大部分工作都包括确保您正在公开正确的数据。有关此架构组件的更多信息,请参阅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()}" />

使用可观察的ViewModel可以更好地控制绑定适配器

您可以使用实现Observable接口的ViewModel组件来通知其他应用程序组件数据中的更改,类似于您使用LiveData对象的方式。

在某些情况下,您可能更喜欢使用实现Observable接口的ViewModel组件而不是使用LiveData对象,即使您失去了LiveData的生命周期管理功能。使用实现ObservableViewModel组件可以让您更好地控制应用程序中的绑定适配器。例如,此模式可以让您更好地控制数据更改时的通知;它还允许您指定一个自定义方法来在双向数据绑定中设置属性的值。

要实现可观察的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);
    }
}

其他资源

要了解有关数据绑定的更多信息,请参阅以下其他资源。