Per osservabilità si intende la capacità di un oggetto di informare altre persone delle modifiche apportate ai suoi dati. La libreria di associazione dei dati consente di rendere osservabili oggetti, campi o raccolte.
Puoi utilizzare qualsiasi oggetto per l'associazione di dati, ma la modifica dell'oggetto non determina automaticamente l'aggiornamento dell'interfaccia utente. Puoi utilizzare l'associazione di dati per consentire agli oggetti di dati di inviare notifiche ad altri oggetti, noti come listener, quando i dati cambiano. Esistono tre tipi di classi osservabili: campi, raccolte e oggetti.
Quando uno di questi oggetti di dati osservabili è associato all'interfaccia utente e una proprietà dell'oggetto dati cambia, l'interfaccia utente si aggiorna automaticamente.
Campi osservabili
Se le tue classi hanno solo poche proprietà, potrebbe non valere la pena creare classi che implementino l'interfaccia di Observable
. In questo caso, puoi utilizzare la classe generica Observable
e le seguenti classi primitive specifiche per rendere osservabili i campi:
ObservableBoolean
ObservableByte
ObservableChar
ObservableShort
ObservableInt
ObservableLong
ObservableFloat
ObservableDouble
ObservableParcelable
I campi osservabili sono oggetti osservabili autonomi che hanno un singolo campo. Le versioni primitive evitano di "boxing" e "unboxing" durante le operazioni di accesso. Per utilizzare questo meccanismo, crea una proprietà public final
nel linguaggio di programmazione Java o una proprietà di sola lettura in Kotlin, come mostrato nell'esempio seguente:
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(); }
Per accedere al valore del campo, utilizza i metodi della funzione di accesso set()
e get()
oppure la sintassi della proprietà Kotlin:
Kotlin
user.firstName = "Google" val age = user.age
Java
user.firstName.set("Google"); int age = user.age.get();
Raccolte osservabili
Alcune app utilizzano strutture dinamiche per conservare i dati. Le raccolte osservabili consentono
di accedere a queste strutture tramite una chiave. La classe ObservableArrayMap
è utile quando la chiave è un tipo di riferimento, come String
, come mostrato nell'esempio seguente:
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);
Nel layout puoi trovare la mappa utilizzando le chiavi stringa, come mostrato nell'esempio seguente:
<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
è utile quando la chiave è un numero intero, come segue:
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);
Nel layout puoi accedere all'elenco tramite gli indici, come mostrato nell'esempio seguente:
<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"/>
Oggetti osservabili
Una classe che implementa l'interfaccia Observable
consente la registrazione degli ascoltatori che vogliono ricevere una notifica in caso di modifiche alle proprietà dell'oggetto osservabile.
L'interfaccia Observable
dispone di un meccanismo per aggiungere e rimuovere i listener, ma sei tu a decidere quando inviare le notifiche. Per semplificare lo sviluppo, la libreria
DataBinding fornisce la classe BaseObservable
, che
implementa il meccanismo di registrazione listener. La classe di dati che implementa BaseObservable
è responsabile dell'invio di una notifica quando le proprietà cambiano. A questo scopo, assegna un'annotazione Bindable
al getter e chiama il metodo notifyPropertyChanged()
nel setter, come mostrato nell'esempio seguente:
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); } }
L'associazione di dati genera una classe denominata BR
nel pacchetto del modulo, che contiene gli ID delle risorse utilizzate per l'associazione di dati. L'annotazione Bindable
genera una voce nel file della classe BR
durante la compilazione. Se la classe base
per le classi di dati non può essere modificata, puoi implementare l'interfaccia Observable
utilizzando un oggetto
PropertyChangeRegistry
per registrare e inviare notifiche ai listener in modo efficiente.
Oggetti sensibili al ciclo di vita
I layout nella tua app possono anche essere associati a origini di associazione di dati che segnalano automaticamente all'interfaccia utente le modifiche ai dati. In questo modo, le associazioni sono sensibili al ciclo di vita e vengono attivate solo quando l'interfaccia utente è visibile sullo schermo.
L'associazione di dati supporta
StateFlow
e
LiveData
. Per ulteriori informazioni sull'utilizzo di LiveData
nell'associazione di dati, consulta Utilizzare LiveData per notificare l'interfaccia utente in caso di modifiche ai dati.
Utilizza StateFlow
Se la tua app utilizza Kotlin con le coroutine, puoi utilizzare gli oggetti StateFlow
come origine di associazione di dati. Per utilizzare un oggetto StateFlow
con la classe di associazione, specifica un proprietario del ciclo di vita per definire l'ambito dell'oggetto StateFlow
. L'esempio seguente specifica l'attività come proprietario del ciclo di vita dopo la creazione dell'istanza della classe di associazione:
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
}
}
Come descritto in Associa le viste del layout ai componenti dell'architettura, l'associazione di dati funziona perfettamente con gli oggetti ViewModel
. Puoi utilizzare StateFlow
e ViewModel
insieme nel seguente modo:
class ScheduleViewModel : ViewModel() {
private val _username = MutableStateFlow<String>("")
val username: StateFlow<String> = _username
init {
viewModelScope.launch {
_username.value = Repository.loadUserName()
}
}
}
Nel layout, assegna le proprietà e i metodi dell'oggetto ViewModel
alle viste corrispondenti utilizzando espressioni di associazione, come mostrato nell'esempio seguente:
<TextView
android:id="@+id/name"
android:text="@{viewmodel.username}" />
L'interfaccia utente si aggiorna automaticamente ogni volta che il valore del nome dell'utente cambia.
Disabilita il supporto di StateFlow
Per le app che utilizzano Kotlin e AndroidX, il supporto di StateFlow
è incluso
automaticamente nell'associazione di dati. Ciò significa che la dipendenza delle coroutine viene inclusa automaticamente nell'app se la dipendenza non è già disponibile.
Puoi disattivare questa funzionalità aggiungendo quanto segue al tuo file build.gradle
:
Trendy
android { ... dataBinding { addKtx = false } }
Kotlin
android { ... dataBinding { addKtx = false } }
In alternativa, puoi disabilitare StateFlow
a livello globale nel progetto aggiungendo
la seguente riga al file gradle.properties
:
Trendy
android.defaults.databinding.addKtx = false
Kotlin
android.defaults.databinding.addKtx = false
Risorse aggiuntive
Per scoprire di più sull'associazione di dati, consulta le risorse aggiuntive riportate di seguito:
Samples
Codelab
Post del blog
Consigliato per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Modulo Stato salvato per ViewModel
- Associare le viste del layout ai componenti dell'architettura
- Panoramica della libreria di pagine di destinazione