將版面配置視圖與架構元件建立繫結

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);
    }
}

其他資源

如要進一步瞭解資料繫結,請參閱下列其他資源。