使用可觀察的資料物件

觀測能力是指物件在資料變更時通知其他人的功能。資料繫結程式庫可讓您將物件、欄位或集合設為可觀察。

您可以使用任何物件進行資料繫結,但修改物件不會自動導致 UI 更新。您可以使用資料繫結,讓資料物件在資料變更時通知其他物件 (稱為事件監聽器)。可觀察類別分為三種:欄位集合物件

當這些可觀測資料物件繫結至 UI,且資料物件的屬性有所變更時,UI 會自動更新。

可觀察欄位

如果您的類別只有少數屬性,則建立實作 Observable 介面的類別可能並不值得。在此情況下,您可以使用一般 Observable 類別和下列原始類別,讓欄位變成可觀察狀態:

可觀察欄位是獨立的可觀察物件,其中包含單一欄位。原始版本可避免在存取作業期間進行拳擊和開箱。如要使用這項機制,請以 Java 程式設計語言建立 public final 屬性,或在 Kotlin 中建立唯讀屬性,如以下範例所示:

Kotlin

class User {
    val firstName = ObservableField<String>()
    val lastName = ObservableField<String>()
    val age = ObservableInt()
}

Java

private static class User {
    public final ObservableField<String> firstName = new ObservableField<>();
    public final ObservableField<String> lastName = new ObservableField<>();
    public final ObservableInt age = new ObservableInt();
}

如要存取欄位值,請使用 set()get() 存取子方法,或使用 Kotlin 屬性語法

Kotlin

user.firstName = "Google"
val age = user.age

Java

user.firstName.set("Google");
int age = user.age.get();

可觀察的集合

部分應用程式會使用動態結構保留資料。可觀測的集合可讓您使用索引鍵存取這些結構。當鍵是參照類型 (例如 String) 時,ObservableArrayMap 類別非常實用,如以下範例所示:

Kotlin

ObservableArrayMap<String, Any>().apply {
    put("firstName", "Google")
    put("lastName", "Inc.")
    put("age", 17)
}

Java

ObservableArrayMap<String, Object> user = new ObservableArrayMap<>();
user.put("firstName", "Google");
user.put("lastName", "Inc.");
user.put("age", 17);

在版面配置中,您可以使用字串鍵尋找地圖,如以下範例所示:

<data>
    <import type="android.databinding.ObservableMap"/>
    <variable name="user" type="ObservableMap&lt;String, Object&gt;"/>
</data>
…
<TextView
    android:text="@{user.lastName}"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
<TextView
    android:text="@{String.valueOf(1 + (Integer)user.age)}"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>

當索引鍵是整數時,ObservableArrayList 類別非常實用,如下所示:

Kotlin

ObservableArrayList<Any>().apply {
    add("Google")
    add("Inc.")
    add(17)
}

Java

ObservableArrayList<Object> user = new ObservableArrayList<>();
user.add("Google");
user.add("Inc.");
user.add(17);

在版面配置中,您可以透過索引存取清單,如以下範例所示:

<data>
    <import type="android.databinding.ObservableList"/>
    <import type="com.example.my.app.Fields"/>
    <variable name="user" type="ObservableList&lt;Object&gt;"/>
</data>
…
<TextView
    android:text='@{user[Fields.LAST_NAME]}'
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
<TextView
    android:text='@{String.valueOf(1 + (Integer)user[Fields.AGE])}'
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>

可觀察的物件

藉由實作 Observable 介面的類別,您可以註冊監聽器,接收可觀測物件的屬性變更通知。

Observable 介面提供新增和移除事件監聽器的機制,但您可以決定通知的傳送時間。為簡化開發作業,資料繫結程式庫提供 BaseObservable 類別,其會實作事件監聽器註冊機制。實作 BaseObservable 的資料類別負責在屬性變更時收到通知。方法是將 Bindable 註解指派給 getter,然後在 setter 中呼叫 notifyPropertyChanged() 方法,如以下範例所示:

Kotlin

class User : BaseObservable() {

    @get:Bindable
    var firstName: String = ""
        set(value) {
            field = value
            notifyPropertyChanged(BR.firstName)
        }

    @get:Bindable
    var lastName: String = ""
        set(value) {
            field = value
            notifyPropertyChanged(BR.lastName)
        }
}

Java

private static class User extends BaseObservable {
    private String firstName;
    private String lastName;

    @Bindable
    public String getFirstName() {
        return this.firstName;
    }

    @Bindable
    public String getLastName() {
        return this.lastName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
        notifyPropertyChanged(BR.firstName);
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
        notifyPropertyChanged(BR.lastName);
    }
}

資料繫結會在模組套件中產生名為 BR 的類別,其中包含用於資料繫結的資源 ID。Bindable 註解會在編譯期間產生 BR 類別檔案中的項目。如果資料類別的基礎類別無法變更,您可以使用 PropertyChangeRegistry 物件實作 Observable 介面,有效率地註冊及通知事件監聽器。

生命週期感知物件

應用程式中的版面配置也可以繫結至資料繫結來源,自動向 UI 通知資料異動。如此一來,繫結具有生命週期感知特性,且只會於 UI 在畫面上顯示時觸發。

資料繫結支援 StateFlowLiveData。如要進一步瞭解如何在資料繫結中使用 LiveData,請參閱「使用 LiveData 通知 UI 有關資料變更的資訊」。

使用 StateFlow

如果應用程式將 Kotlin 與協同程式搭配使用,您可以使用 StateFlow 物件做為資料繫結來源。如要將 StateFlow 物件與繫結類別搭配使用,請指定生命週期擁有者來定義 StateFlow 物件的範圍。以下範例指定在繫結類別執行個體化後,將活動指定為生命週期擁有者:

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.lifecycleOwner = this
    }
}

如「架構元件的繫結版面配置檢視畫面」所述,資料繫結可與 ViewModel 物件完美搭配運作。您可以同時使用 StateFlowViewModel,如下所示:

class ScheduleViewModel : ViewModel() {

    private val _username = MutableStateFlow<String>("")
    val username: StateFlow<String> = _username

    init {
        viewModelScope.launch {
            _username.value = Repository.loadUserName()
        }
    }
}

在版面配置中,使用繫結運算式將 ViewModel 物件的屬性和方法指派給對應的檢視畫面,如以下範例所示:

<TextView
    android:id="@+id/name"
    android:text="@{viewmodel.username}" />

每當使用者名稱值變更時,使用者介面就會自動更新。

停用 StateFlow 支援

如果應用程式使用 Kotlin 和 AndroidX,資料繫結會自動納入 StateFlow 支援功能。這表示如果協同程式尚未取得依附元件,會自動在應用程式中加入協同程式依附元件。

如要停用這項功能,請在 build.gradle 檔案中加入以下內容:

Groovy

android {
    ...
    dataBinding {
        addKtx = false
    }
}

Kotlin

android {
    ...
    dataBinding {
        addKtx = false
    }
}

您也可以在 gradle.properties 檔案中加入以下這行程式碼,在專案中全域停用 StateFlow

Groovy

android.defaults.databinding.addKtx = false

Kotlin

android.defaults.databinding.addKtx = false

其他資源

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

範例

程式碼研究室

網誌文章