Mit beobachtbaren Datenobjekten arbeiten

Beobachtbarkeit bezieht sich auf die Fähigkeit eines Objekts, andere über Änderungen an seinen Daten zu informieren. Mit der Data Binding Library können Sie Objekte, Felder oder Sammlungen beobachtbar machen.

Sie können ein beliebiges Objekt für die Datenbindung verwenden. Durch das Ändern des Objekts wird jedoch nicht automatisch die UI aktualisiert. Mithilfe der Datenbindung können Sie Ihren Datenobjekten die Möglichkeit geben, andere Objekte (sogenannte Listener) zu benachrichtigen, wenn sich ihre Daten ändern. Es gibt drei Arten von beobachtbaren Klassen: Felder, Sammlungen und Objekte.

Wenn eines dieser beobachtbaren Datenobjekte an die UI gebunden ist und sich eine Eigenschaft des Datenobjekts ändert, wird die UI automatisch aktualisiert.

Beobachtbare Felder

Wenn Ihre Klassen nur wenige Attribute haben, lohnt es sich möglicherweise nicht, Klassen zu erstellen, die die Schnittstelle Observable implementieren. In diesem Fall können Sie die generische Observable-Klasse und die folgenden primitiven Klassen verwenden, um Felder beobachtbar zu machen:

Beobachtbare Felder sind eigenständige beobachtbare Objekte mit einem einzelnen Feld. Die primitiven Versionen vermeiden Boxen und Unboxing während Zugriffvorgängen. Um diesen Mechanismus zu verwenden, erstellen Sie ein public final-Attribut in der Programmiersprache Java oder ein schreibgeschütztes Attribut in Kotlin, wie im folgenden Beispiel gezeigt:

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

Verwenden Sie die Zugriffsmethoden set() und get() oder die Kotlin-Attributsyntax, um auf den Feldwert zuzugreifen:

Kotlin

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

Java

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

Beobachtbare Sammlungen

Einige Apps verwenden dynamische Strukturen zur Speicherung von Daten. Beobachtbare Sammlungen ermöglichen den Zugriff auf diese Strukturen mithilfe eines Schlüssels. Die Klasse ObservableArrayMap ist nützlich, wenn der Schlüssel ein Referenztyp wie String ist, wie im folgenden Beispiel gezeigt:

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

Im Layout finden Sie die Karte mithilfe der Stringschlüssel, wie im folgenden Beispiel gezeigt:

<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"/>

Die Klasse ObservableArrayList ist nützlich, wenn der Schlüssel eine Ganzzahl ist:

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

Im Layout können Sie wie im folgenden Beispiel über die Indexe auf die Liste zugreifen:

<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"/>

Beobachtbare Objekte

Eine Klasse, die die Observable-Schnittstelle implementiert, ermöglicht die Registrierung von Listenern, die über Attributänderungen des beobachtbaren Objekts benachrichtigt werden möchten.

Die Schnittstelle Observable verfügt über einen Mechanismus zum Hinzufügen und Entfernen von Listenern. Sie entscheiden jedoch, wann Benachrichtigungen gesendet werden. Zur Vereinfachung der Entwicklung stellt die Datenbindungsbibliothek die Klasse BaseObservable bereit, die den Listener-Registrierungsmechanismus implementiert. Die Datenklasse, in der BaseObservable implementiert ist, sendet Benachrichtigungen, wenn sich die Attribute ändern. Weisen Sie dazu dem Getter eine Bindable-Annotation zu und rufen Sie die Methode notifyPropertyChanged() im Setter auf, wie im folgenden Beispiel gezeigt:

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

Die Datenbindung generiert im Modulpaket eine Klasse mit dem Namen BR, die die IDs der für die Datenbindung verwendeten Ressourcen enthält. Die Annotation Bindable generiert während der Kompilierung einen Eintrag in der Klassendatei BR. Wenn die Basisklasse für Datenklassen nicht geändert werden kann, können Sie die Observable-Schnittstelle mithilfe eines PropertyChangeRegistry-Objekts implementieren, um Listener effizient zu registrieren und zu benachrichtigen.

Lebenszyklusbewusste Objekte

Die Layouts in Ihrer App können auch an Datenbindungsquellen gebunden werden, die die UI automatisch über Änderungen der Daten informieren. Auf diese Weise werden Ihre Bindungen Lebenszyklus berücksichtigen und nur ausgelöst, wenn die UI auf dem Bildschirm sichtbar ist.

Die Datenbindung unterstützt StateFlow und LiveData. Weitere Informationen zur Verwendung von LiveData in der Datenbindung finden Sie unter Mit LiveData die UI über Datenänderungen informieren.

StateFlow verwenden

Wenn in Ihrer App Kotlin mit Koroutinen verwendet wird, können Sie StateFlow-Objekte als Quelle für die Datenbindung verwenden. Wenn Sie ein StateFlow-Objekt mit Ihrer Bindungsklasse verwenden möchten, geben Sie einen Lebenszyklusinhaber an, um den Bereich des StateFlow-Objekts zu definieren. Im folgenden Beispiel wird die Aktivität als Lebenszyklusinhaber angegeben, nachdem die Bindungsklasse instanziiert wurde:

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

Wie unter Layoutansichten an Architekturkomponenten binden beschrieben, funktioniert die Datenbindung nahtlos mit ViewModel-Objekten. So können Sie StateFlow und ViewModel zusammen verwenden:

class ScheduleViewModel : ViewModel() {

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

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

Weisen Sie in Ihrem Layout die Eigenschaften und Methoden des ViewModel-Objekts den entsprechenden Ansichten mithilfe von Bindungsausdrücken zu, wie im folgenden Beispiel gezeigt:

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

Die Benutzeroberfläche wird automatisch aktualisiert, wenn sich der Name-Wert des Nutzers ändert.

StateFlow-Unterstützung deaktivieren

Für Apps, die Kotlin und AndroidX verwenden, ist die StateFlow-Unterstützung automatisch in der Datenbindung enthalten. Das bedeutet, dass die Koroutinenabhängigkeit automatisch in Ihre Anwendung aufgenommen wird, wenn sie nicht bereits verfügbar ist.

Sie können diese Funktion deaktivieren, indem Sie der Datei build.gradle Folgendes hinzufügen:

Groovig

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

Kotlin

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

Alternativ können Sie StateFlow global in Ihrem Projekt deaktivieren, indem Sie die folgende Zeile in die Datei gradle.properties einfügen:

Groovig

android.defaults.databinding.addKtx = false

Kotlin

android.defaults.databinding.addKtx = false

Weitere Informationen

Weitere Informationen zur Datenbindung finden Sie in den folgenden Ressourcen:

Produktproben

Codelabs

Blogposts