web-dev-qa-db-fra.com

Utilisation de LiveData avec la liaison de données

Avec la stabilisation des composants de l'architecture Android, j'ai commencé à mettre à jour tous mes ViewModels de base vers la nouvelle implémentation de ViewModel . D'après ce que j'ai compris, il est recommandé d'utiliser LiveData pour contenir la classe Model car elle gère mieux le cycle de vie.

J'aime utiliser Data Binding car cela clarifie le code côté Java/Kotlin et qu'il n'est pas nécessaire de "surveiller" les modifications de valeur pour mettre à jour l'interface utilisateur. Cependant, la disposition utilisant uniquement Data Binding observe les données, si les modifications apportées à Model (ou au ViewModel) sont étendues BaseObservable et LiveData ne le sont pas. Je comprends que l’un des objectifs principaux de LiveData doit être observé et met à jour l’UI par programme, mais pour les mises à jour simples, Data Binding est très utile.

Ce problème avait déjà été signalé ( GitHub et Stack Overflow ) et d’abord il a été dit que la version 1.0 l’aurait et on dit maintenant que cette fonctionnalité est en développement.

Afin d'utiliser à la fois LiveData et Data Binding, j'ai créé une implémentation très simple de la classe qui étend BaseObservable:

import Android.Arch.lifecycle.LiveData
import Android.Arch.lifecycle.MutableLiveData
import Android.databinding.BaseObservable

class ObservableMutableLiveData<T>() : BaseObservable() {

    private var data: MutableLiveData<T> = MutableLiveData()

    constructor(data: T) : this() {
        this.data.value = data
    }

    public fun set(value: T) {
        if (value != data.value) {
            data.value = value
            notifyChange()
        }
    }

    public fun get(): T? {
        return data.value
    }

    public fun getObservable(): LiveData<T> {
        return data
    }
}

Donc, fondamentalement, mon ObservableMutableLiveData est une copie de ObservableField qui utilise LiveData pour stocker le modèle et avec cette implémentation, la mise à jour est mise à jour après chaque mise à jour du modèle.

Les questions sont:

  • Est-ce une mauvaise implémentation de LiveData? Ce wrapper "casse-t-il" les fonctionnalités de LiveData, telles que le cycle de vie?
  • D'après ce que j'ai compris, LiveData est le nouveau ObservableField. Est-ce correct?
19
Igor Escodro

Android Studio 3.1 (actuellement dans Canary 6) résoudra ce problème, car LiveData peut être utilisé comme observable field:

Mises à jour de la liaison de données:

Vous pouvez maintenant utiliser un objet LiveData en tant que champ observable dans les expressions de liaison de données. La classe ViewDataBinding inclut désormais une nouvelle méthode setLifecycle que vous devez utiliser pour observer les objets LiveData.

Source: Android Studio 3.1 Canary 6 est maintenant disponible

12
Igor Escodro

Pour ceux qui ont trouvé cette question en cherchant un exemple comme moi, en voici une:

Dans la mise en page .xml, mettez l'élément LiveData avec son type:

<layout>
    <data>
        <variable
            name="myString"
            type="Android.Arch.lifecycle.MutableLiveData&lt;String&gt;"/>
    </data>

    ...

    <TextView
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:text='@{myString}'
        ...
     />

    ...

</layout>

Dans votre code, définissez sa valeur et le propriétaire du cycle de vie:

MutableLiveData<String> myString = new MutableLiveData<>();

...

binding.setLifecycleOwner(this);
binding.setMyString(myString);

C'est tout :)

Notez que la valeur par défaut de LiveData elements est null. Par conséquent, affectez des valeurs initiales pour vous assurer d'obtenir immédiatement l'effet souhaité ou utilisez this pour appliquer la nullabilité.

13
Sir Codesalot

Pour Androidx sera:

androidx.lifecycle.MutableLiveData

<layout>
    <data>
        <variable
            name="myString"
            type="androidx.lifecycle.MutableLiveData;String&gt;"/>
    </data>

    ...

    <TextView
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:text='@{myString}'
        ...
     />

    ...

</layout>

Et pour Kotlin:

  val myStr = MutableLiveData<String>()

...

 binding.apply {
            setLifecycleOwner(this)
            this.myString = myStr
        }

Bonne chance! :)

0
Serg Burlaka