Utiliser les objets de données observables

L'observabilité fait référence à la capacité d'un objet à informer les autres utilisateurs des modifications de ses données. La bibliothèque Data Binding vous permet de créer des objets, des champs ou des collections observables.

Vous pouvez utiliser n'importe quel objet pour la liaison de données, mais la modification de l'objet entraîne automatiquement la mise à jour de l'interface utilisateur. Vous pouvez utiliser la liaison de données pour attribuer aux objets la possibilité d'envoyer une notification à d'autres objets, appelés écouteurs, lorsque leurs données changent. Il existe trois types de classes observables: champs, collections et objets.

Lorsque l'un de ces objets de données observables est lié à l'interface utilisateur et qu'une propriété de l'objet de données change, l'UI est automatiquement mise à jour.

Champs observables

Si vos classes ne comportent que quelques propriétés, cela n'en vaut peut-être pas la peine. créer des classes qui implémentent la Observable. Dans ce vous pouvez utiliser la classe générique Observable et pour rendre les champs observables:

Les champs observables sont des objets observables autonomes qui ont un seul . Les versions primitives évitent le boxing et le déballage lors de l'accès. opérations. Pour utiliser ce mécanisme, créez une propriété public final dans l'environnement Java ou une propriété en lecture seule en Kotlin, comme illustré dans l'exemple suivant:

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

Pour accéder à la valeur du champ, utilisez la méthode set() et Méthodes d'accesseur get() ou utilisez une propriété Kotlin :

Kotlin

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

Java

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

Collections observables

Certaines applications utilisent des structures dynamiques pour stocker les données. Les collections observables permettent l'accès à ces structures à l'aide d'une clé. La Classe ObservableArrayMap est utile lorsque la clé est un type de référence, tel que String, comme indiqué dans les l'exemple suivant:

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

Dans la mise en page, vous pouvez trouver la carte à l'aide des touches de chaîne, comme indiqué dans les l'exemple suivant:

<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 est utile lorsque la clé est un entier, comme suit:

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

Dans la mise en page, vous pouvez accéder à la liste via les index, comme indiqué dans la section l'exemple suivant:

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

Objets observables

Une classe qui implémente l'interface Observable permet d'enregistrer les écouteurs qui souhaitent être avertis des modifications de propriétés de l'objet observable .

L'interface Observable dispose d'un mécanisme permettant d'ajouter et de supprimer des écouteurs, mais vous décider du moment où les notifications sont envoyées. Pour faciliter le développement, Binding Library fournit BaseObservable, qui met en œuvre le mécanisme d'enregistrement des écouteurs. La classe de données qui implémente BaseObservable est chargé de vous avertir lorsque les établissements changent. À faire attribuer une annotation Bindable au getter et appeler la méthode notifyPropertyChanged() dans le setter, comme illustré dans l'exemple suivant:

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

La liaison de données génère une classe nommée BR dans le package de module, qui contient les ID des ressources utilisées pour la liaison de données. L'annotation Bindable génère une entrée dans le fichier de classe BR lors de la compilation. Si la classe de base ne peuvent pas être modifiées pour les classes de données, vous pouvez implémenter l'interface Observable à l'aide d'un PropertyChangeRegistry pour enregistrer et notifier efficacement les écouteurs.

Objets tenant compte des cycles de vie

Les mises en page de votre application peuvent également être liées à des sources de liaison de données qui pour informer l'interface utilisateur des modifications apportées aux données. De cette façon, vos liaisons tenant compte du cycle de vie et ne sont déclenchés que lorsque l'interface utilisateur est visible à l'écran.

Compatibilité avec la liaison de données StateFlow et LiveData Pour en savoir plus sur à l'aide de LiveData dans la liaison de données, consultez la section Utiliser LiveData pour informer l'interface utilisateur des données modifications.

Utiliser StateFlow

Si votre application utilise Kotlin avec des coroutines, vous pouvez utiliser StateFlow comme source de liaison de données. Pour utiliser un objet StateFlow avec votre classe de liaison, spécifiez un propriétaire de cycle de vie pour définir le champ d'application StateFlow. L'exemple suivant spécifie l'activité comme propriétaire du cycle de vie après l'instanciation de la classe de liaison:

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

Comme décrit dans la section Lier des vues de mise en page à l'architecture Composants, liaison de données s'intègre parfaitement à ViewModel d'objets. Vous pouvez utiliser StateFlow et ViewModel ensemble comme suit:

class ScheduleViewModel : ViewModel() {

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

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

Dans votre mise en page, attribuez les propriétés et les méthodes de votre objet ViewModel aux éléments suivants : les vues correspondantes à l'aide d'expressions de liaison, comme illustré dans Exemple:

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

L'interface utilisateur est automatiquement mise à jour chaque fois que la valeur du nom de l'utilisateur change.

Désactiver la compatibilité avec StateFlow

Pour les applications qui utilisent Kotlin et AndroidX, la prise en charge de StateFlow est automatique incluses dans la liaison de données. Cela signifie que la dépendance des coroutines est automatiquement inclus dans votre application si la dépendance n'est pas déjà disponible.

Vous pouvez désactiver cette fonctionnalité en ajoutant les éléments suivants à votre Fichier build.gradle:

Groovy

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

Kotlin

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

Vous pouvez également désactiver StateFlow de manière globale dans votre projet en ajoutant la ligne suivante au fichier gradle.properties:

Groovy

android.defaults.databinding.addKtx = false

Kotlin

android.defaults.databinding.addKtx = false

Ressources supplémentaires

Pour en savoir plus sur la liaison de données, consultez les ressources suivantes:

Exemples

Ateliers de programmation

Articles de blog