L'observabilité fait référence à la capacité d'un objet à avertir les autres utilisateurs des modifications apportées à ses données. La bibliothèque Data Binding vous permet de rendre 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 n'entraîne pas automatiquement la mise à jour de l'interface utilisateur. Vous pouvez utiliser la liaison de données pour permettre à vos objets de données d'informer d'autres objets (appelés "écouteurs") lorsque leurs données changent. Il existe trois types de classes observables : les champs, les collections et les objets.
Lorsque l'un de ces objets de données observables est lié à l'UI et qu'une propriété de l'objet de données change, l'UI est automatiquement mise à jour.
Champs observables
Si vos classes ne possèdent que quelques propriétés, il peut s'avérer inutile de créer des classes qui implémentent l'interface Observable
. Dans ce cas, vous pouvez utiliser la classe générique Observable
et les classes spécifiques aux primitives suivantes pour rendre les champs observables:
ObservableBoolean
ObservableByte
ObservableChar
ObservableShort
ObservableInt
ObservableLong
ObservableFloat
ObservableDouble
ObservableParcelable
Les champs observables sont des objets observables autonomes possédant un seul champ. Les versions primitives évitent le boxing et le déballage lors des opérations d'accès. Pour utiliser ce mécanisme, créez une propriété public final
dans le langage de programmation 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 les méthodes d'accesseur set()
et get()
, ou la syntaxe des propriétés 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 d'accéder à 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 illustré dans 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 de clés de chaîne, comme illustré dans l'exemple suivant:
<data>
<import type="android.databinding.ObservableMap"/>
<variable name="user" type="ObservableMap<String, Object>"/>
</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"/>
La classe 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 illustré dans l'exemple suivant:
<data>
<import type="android.databinding.ObservableList"/>
<import type="com.example.my.app.Fields"/>
<variable name="user" type="ObservableList<Object>"/>
</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 informés 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écidez quand les notifications sont envoyées. Pour faciliter le développement, la bibliothèque Data Binding fournit la classe BaseObservable
, qui implémente le mécanisme d'enregistrement de l'écouteur. La classe de données qui implémente BaseObservable
est chargée d'envoyer une notification lorsque les propriétés changent. Pour ce faire, attribuez une annotation Bindable
au getter et appelez 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 des classes de données ne peut pas être modifiée, vous pouvez implémenter l'interface Observable
à l'aide d'un objet PropertyChangeRegistry
pour enregistrer et avertir efficacement les écouteurs.
Objets tenant compte des cycles de vie
Les mises en page de votre application peuvent également être associées à des sources de liaison de données qui informent automatiquement l'interface utilisateur des modifications apportées aux données. Ainsi, vos liaisons tiennent compte du cycle de vie et ne sont déclenchées que lorsque l'interface utilisateur est visible à l'écran.
La liaison de données est compatible avec StateFlow
et LiveData
. Pour en savoir plus sur l'utilisation de LiveData
dans la liaison de données, consultez Utiliser LiveData pour informer l'interface utilisateur des modifications de données.
Utiliser StateFlow
Si votre application utilise Kotlin avec des coroutines, vous pouvez utiliser des objets StateFlow
comme source de liaison de données. Pour utiliser un objet StateFlow
avec votre classe de liaison, spécifiez un propriétaire du cycle de vie afin de définir le champ d'application de l'objet StateFlow
. L'exemple suivant spécifie l'activité en tant que propriétaire du cycle de vie une fois la classe de liaison instanciée:
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 aux composants d'architecture, la liaison de données fonctionne parfaitement avec les objets ViewModel
. 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 vues correspondantes à l'aide d'expressions de liaison, comme illustré dans l'exemple suivant:
<TextView
android:id="@+id/name"
android:text="@{viewmodel.username}" />
L'interface utilisateur est automatiquement mise à jour chaque fois que le nom de l'utilisateur change.
Désactiver la prise en charge de StateFlow
Pour les applications qui utilisent Kotlin et AndroidX, la prise en charge de StateFlow
est automatiquement incluse dans la liaison de données. Cela signifie que la dépendance des coroutines est automatiquement incluse dans votre application si elle n'est pas déjà disponible.
Vous pouvez désactiver cette fonctionnalité en ajoutant le code suivant à votre fichier build.gradle
:
Groovy
android { ... dataBinding { addKtx = false } }
Kotlin
android { ... dataBinding { addKtx = false } }
Vous pouvez également désactiver StateFlow
globalement 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
Recommandations personnalisées
- Remarque : Le texte du lien s'affiche lorsque JavaScript est désactivé
- Module Saved State pour ViewModel
- Lier des vues de mise en page aux composants d'architecture
- Présentation de la bibliothèque Paging