Classi di associazione generate

La libreria Data Binding genera classi di associazione che puoi utilizzare per accedere alle variabili e alle viste del layout. Questa documentazione mostra come creare e personalizzare le classi di associazione generate.

La classe di associazione generata collega le variabili di layout alle viste all'interno del layout. Puoi personalizzare il nome e il pacchetto dell'associazione. Tutte le classi di associazione generate ereditano dalla classe ViewDataBinding.

Per ogni file di layout viene generata una classe di associazione. Per impostazione predefinita, il nome della classe è il nome del file di layout convertito in maiuscole/minuscole Pascal a cui è stato aggiunto il suffisso Binding. Quindi, ad esempio, se il nome file del layout è activity_main.xml, la classe generata corrispondente è ActivityMainBinding. Questa classe contiene tutte le associazioni dalle proprietà del layout alle viste del layout e sa come assegnare valori per le espressioni di associazione.

Crea un oggetto di associazione

L'oggetto di associazione viene creato immediatamente dopo l'aumento delle dimensioni del layout per garantire che la gerarchia delle viste non venga modificata prima dell'associazione alle viste con espressioni all'interno del layout. Il metodo più comune per associare l'oggetto a un layout è utilizzare i metodi statici nella classe di associazione. Puoi gonfiare la gerarchia delle visualizzazioni e associare l'oggetto utilizzando il metodo inflate() della classe di associazione, come mostrato nell'esempio seguente:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    val binding: MyLayoutBinding = MyLayoutBinding.inflate(layoutInflater)

    setContentView(binding.root)
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    MyLayoutBinding binding = MyLayoutBinding.inflate(getLayoutInflater());

    setContentView(binding.root);
}

Esiste una versione alternativa del metodo inflate() che accetta un oggetto ViewGroup oltre all'oggetto LayoutInflater , come mostrato nell'esempio seguente:

Kotlin

val binding: MyLayoutBinding = MyLayoutBinding.inflate(getLayoutInflater(), viewGroup, false)

Java

MyLayoutBinding binding = MyLayoutBinding.inflate(getLayoutInflater(), viewGroup, false);

Se il layout viene gonfiato utilizzando un meccanismo diverso, puoi associarlo separatamente, come segue:

Kotlin

val binding: MyLayoutBinding = MyLayoutBinding.bind(viewRoot)

Java

MyLayoutBinding binding = MyLayoutBinding.bind(viewRoot);

A volte non conosci il tipo di associazione in anticipo. In questi casi, puoi creare l'associazione utilizzando la classe DataBindingUtil, come illustrato nel seguente snippet di codice:

Kotlin

val viewRoot = LayoutInflater.from(this).inflate(layoutId, parent, attachToParent)
val binding: ViewDataBinding? = DataBindingUtil.bind(viewRoot)

Java

View viewRoot = LayoutInflater.from(this).inflate(layoutId, parent, attachToParent);
ViewDataBinding binding = DataBindingUtil.bind(viewRoot);

Se utilizzi elementi di associazione di dati all'interno di un adattatore Fragment, ListView o RecyclerView, ti consigliamo di utilizzare i metodi inflate() delle classi di associazioni o la classe DataBindingUtil, come mostrato nell'esempio di codice riportato di seguito:

Kotlin

val listItemBinding = ListItemBinding.inflate(layoutInflater, viewGroup, false)
// or
val listItemBinding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false)

Java

ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);
// or
ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);

Viste con ID

La libreria di associazione dei dati crea un campo immutabile nella classe di associazione per ogni vista che ha un ID nel layout. Ad esempio, la libreria di associazione dati crea i campi firstName e lastName di tipo TextView dal seguente layout:

<layout xmlns:android="http://schemas.android.com/apk/res/android">
   <data>
       <variable name="user" type="com.example.User"/>
   </data>
   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">
       <TextView android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{user.firstName}"
   android:id="@+id/firstName"/>
       <TextView android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{user.lastName}"
  android:id="@+id/lastName"/>
   </LinearLayout>
</layout>

La libreria estrae le viste, inclusi gli ID, dalla gerarchia delle visualizzazioni in un unico passaggio. Questo meccanismo può essere più veloce rispetto alla chiamata del metodo findViewById() per ogni visualizzazione del layout.

Gli ID non sono necessari in quanto senza associazione di dati, ma ci sono ancora alcune istanze in cui l'accesso alle viste è necessario dal codice.

Variabili

La libreria Data Binding genera metodi della funzione di accesso per ogni variabile dichiarata nel layout. Ad esempio, il seguente layout genera metodi setter e getter nella classe di associazione per le variabili user, image e note:

<data>
   <import type="android.graphics.drawable.Drawable"/>
   <variable name="user" type="com.example.User"/>
   <variable name="image" type="Drawable"/>
   <variable name="note" type="String"/>
</data>

Stub di visualizzazione

Diversamente dalle viste normali, gli oggetti ViewStub iniziano come viste invisibili. Quando vengono rese visibili o gonfiate in modo esplicito, si sostituiscono nel layout gonfiando un altro layout.

Poiché ViewStub scompare dalla gerarchia delle visualizzazioni, anche la visualizzazione nell'oggetto di associazione deve scomparire per poter essere rivendicata dalla garbage collection. Poiché le viste sono definitive, un oggetto ViewStubProxy sostituisce ViewStub nella classe di associazione generata, concedendoti l'accesso a ViewStub quando esiste e l'accesso alla gerarchia di visualizzazioni ingrandita quando ViewStub viene aumentato in modo artificioso.

Quando si gonfia un altro layout, è necessario che il nuovo layout venga associato a un'associazione. Di conseguenza, l'elemento ViewStubProxy deve ascoltare l'elemento ViewStub OnInflateListener e stabilire l'associazione quando richiesto. Poiché può esistere un solo listener alla volta, ViewStubProxy consente di impostare un OnInflateListener, che chiama dopo aver stabilito l'associazione.

Associazione immediata

Quando una variabile o un oggetto osservabile cambia, l'associazione è pianificata per cambiare prima del frame successivo. Tuttavia, a volte l'associazione deve essere eseguita immediatamente. Per forzare l'esecuzione, utilizza il metodo executePendingBindings().

Variabili dinamiche

A volte, la classe di associazione specifica è sconosciuta. Ad esempio, un elemento RecyclerView.Adapter che utilizza layout arbitrari non conosce la classe di associazione specifica. Deve assegnare il valore di associazione durante la chiamata al metodo onBindViewHolder().

Nell'esempio seguente, tutti i layout associati da RecyclerView hanno una variabile item. L'oggetto BindingHolder ha un metodo getBinding() che restituisce la classe base ViewDataBinding.

Kotlin

override fun onBindViewHolder(holder: BindingHolder, position: Int) {
    item: T = items.get(position)
    holder.binding.setVariable(BR.item, item);
    holder.binding.executePendingBindings();
}

Java

public void onBindViewHolder(BindingHolder holder, int position) {
    final T item = items.get(position);
    holder.getBinding().setVariable(BR.item, item);
    holder.getBinding().executePendingBindings();
}

Thread in background

Puoi modificare il modello dei dati in un thread in background purché non si tratti di una raccolta. L'associazione di dati localizza ogni variabile o campo durante la valutazione, per evitare problemi di contemporaneità.

Nomi delle classi di associazioni personalizzate

Per impostazione predefinita, una classe di associazione viene generata in base al nome del file di layout, iniziando con una lettera maiuscola, rimuovendo i trattini bassi ( _ ), utilizzando le lettere maiuscole per la lettera successiva e il suffisso Binding. Ad esempio, il file di layout contact_item.xml genera la classe ContactItemBinding. La classe si trova in un pacchetto databinding sotto il pacchetto del modulo. Ad esempio, se il pacchetto di moduli è com.example.my.app, la classe di associazione viene inserita nel pacchetto com.example.my.app.databinding.

Le classi di associazione possono essere rinominate o inserite in pacchetti diversi regolando l'attributo class dell'elemento data. Ad esempio, il seguente layout genera la classe di associazione ContactItem nel pacchetto databinding del modulo corrente:

<data class="ContactItem">
    ...
</data>

Puoi generare la classe di associazione in un altro pacchetto anteponendo al nome della classe un punto. L'esempio seguente genera la classe di associazione nel pacchetto del modulo:

<data class=".ContactItem">
    ...
</data>

Puoi anche utilizzare il nome completo del pacchetto in cui vuoi generare la classe di associazione. L'esempio seguente crea la classe di associazione ContactItem nel pacchetto com.example:

<data class="com.example.ContactItem">
    ...
</data>

Risorse aggiuntive

Per saperne di più sull'associazione di dati, consulta le risorse aggiuntive riportate di seguito.