Visualizza associazione Componente di Android Jetpack.
Il binding delle visualizzazioni è una funzionalità che semplifica la scrittura di codice che interagisce con le visualizzazioni. Una volta attivata la funzionalità di binding delle visualizzazioni in un modulo, viene generata una classe di binding per ogni file di layout XML presente nel modulo. Un'istanza di una classe di binding contiene riferimenti diretti a tutte le visualizzazioni che hanno un ID nel layout corrispondente.
Nella maggior parte dei casi, il binding della vista sostituisce findViewById
.
Configura
L'associazione delle visualizzazioni è attivata su base modulare. Per attivare il binding delle visualizzazioni in un
modulo, imposta l'opzione di compilazione viewBinding
su true
nel file
build.gradle
a livello di modulo, come mostrato nell'esempio seguente:
Groovy
android { ... buildFeatures { viewBinding true } }
Kotlin
android { ... buildFeatures { viewBinding = true } }
Se vuoi che un file di layout venga ignorato durante la generazione delle classi di binding, aggiungi
l'attributo tools:viewBindingIgnore="true"
alla vista principale del file di layout:
<LinearLayout
...
tools:viewBindingIgnore="true" >
...
</LinearLayout>
Utilizzo
Se la visualizzazione del binding è attivata per un modulo, viene generata una classe di binding per ogni file di layout XML contenuto nel modulo. Ogni classe di binding contiene riferimenti alla vista principale e a tutte le viste con un ID. Il nome della classe di binding viene generato convertendo il nome del file XML in lettere maiuscole e aggiungendo la parola "Binding" alla fine.
Ad esempio, considera un file di layout denominato result_profile.xml
che contiene quanto segue:
<LinearLayout ... >
<TextView android:id="@+id/name" />
<ImageView android:cropToPadding="true" />
<Button android:id="@+id/button"
android:background="@drawable/rounded_button" />
</LinearLayout>
La classe di binding generata si chiama ResultProfileBinding
. Questa classe ha due
campi: un TextView
chiamato name
e un Button
chiamato button
. Il
ImageView
nel layout non ha ID, pertanto non vi è alcun riferimento nella
classe di binding.
Ogni classe di binding include anche un metodo getRoot()
, che fornisce un riferimento diretto alla vista principale del file di layout corrispondente. In questo esempio, il metodo getRoot()
nella classe ResultProfileBinding
restituisce la vista radice LinearLayout
.
Le sezioni seguenti mostrano l'utilizzo delle classi di binding generate in attività e frammenti.
Utilizzare l'associazione delle visualizzazioni nelle attività
Per configurare un'istanza della classe di binding da utilizzare con un'attività, svolgi i seguenti passaggi nel metodo onCreate()
dell'attività:
- Chiama il metodo
inflate()
statico incluso nella classe di binding generata. Viene creata un'istanza della classe di binding da utilizzare per l'attività. - Ottieni un riferimento alla vista principale chiamando il metodo
getRoot()
o utilizzando la sintassi della proprietà Kotlin. - Passa la visualizzazione principale a
setContentView()
per impostarla come visualizzazione attiva sullo schermo.
Questi passaggi sono illustrati nell'esempio seguente:
Kotlin
private lateinit var binding: ResultProfileBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ResultProfileBinding.inflate(layoutInflater) val view = binding.root setContentView(view) }
Java
private ResultProfileBinding binding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = ResultProfileBinding.inflate(getLayoutInflater()); View view = binding.getRoot(); setContentView(view); }
Ora puoi utilizzare l'istanza della classe di binding per fare riferimento a qualsiasi visualizzazione:
Kotlin
binding.name.text = viewModel.name binding.button.setOnClickListener { viewModel.userClicked() }
Java
binding.name.setText(viewModel.getName()); binding.button.setOnClickListener(new View.OnClickListener() { viewModel.userClicked() });
Utilizzare l'associazione delle visualizzazioni nei frammenti
Per configurare un'istanza della classe di binding da utilizzare con un frammento, svolgi i seguenti passaggi nel metodo onCreateView()
del frammento:
- Chiama il metodo
inflate()
statico incluso nella classe di binding generata. Viene creata un'istanza della classe di binding da utilizzare per il frammento. - Ottieni un riferimento alla vista principale chiamando il metodo
getRoot()
o utilizzando la sintassi della proprietà Kotlin. - Restituire la visualizzazione principale dal metodo
onCreateView()
per renderla la visualizzazione attiva sullo schermo.
Kotlin
private var _binding: ResultProfileBinding? = null // This property is only valid between onCreateView and // onDestroyView. private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { _binding = ResultProfileBinding.inflate(inflater, container, false) val view = binding.root return view } override fun onDestroyView() { super.onDestroyView() _binding = null }
Java
private ResultProfileBinding binding; @Override public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { binding = ResultProfileBinding.inflate(inflater, container, false); View view = binding.getRoot(); return view; } @Override public void onDestroyView() { super.onDestroyView(); binding = null; }
Ora puoi utilizzare l'istanza della classe di binding per fare riferimento a qualsiasi visualizzazione:
Kotlin
binding.name.text = viewModel.name binding.button.setOnClickListener { viewModel.userClicked() }
Java
binding.name.setText(viewModel.getName()); binding.button.setOnClickListener(new View.OnClickListener() { viewModel.userClicked() });
Fornire suggerimenti per configurazioni diverse
Quando dichiari le visualizzazioni in più configurazioni, a volte può essere utile utilizzare un tipo di visualizzazione diverso a seconda del layout specifico. Il seguente snippet di codice ne mostra un esempio:
# in res/layout/example.xml
<TextView android:id="@+id/user_bio" />
# in res/layout-land/example.xml
<EditText android:id="@+id/user_bio" />
In questo caso, potresti aspettarti che la classe generata esponga un campo userBio
di tipo TextView
, perché TextView
è la classe di base comune. A causa di limitazioni tecniche, il generatore di codice di binding delle visualizzazioni non può determinarlo e genera un campo View
. Ciò richiede il trasferimento del campo in un secondo momento con
binding.userBio as TextView
.
Per aggirare questa limitazione, la visualizzazione della proprietà supporta un attributo tools:viewBindingType
, che ti consente di indicare al compilatore il tipo da utilizzare nel codice generato.
Nell'esempio precedente, puoi utilizzare questo attributo per fare in modo che il compilatore generi il campo come TextView
:
# in res/layout/example.xml (unchanged)
<TextView android:id="@+id/user_bio" />
# in res/layout-land/example.xml
<EditText android:id="@+id/user_bio" tools:viewBindingType="TextView" />
In un altro esempio, supponiamo che tu abbia due layout, uno contenente un BottomNavigationView
e un altro contenente un NavigationRailView
. Entrambe le classi estendono NavigationBarView
, che contiene la maggior parte dei dettagli di implementazione. Se il codice non deve sapere esattamente quale sottoclasse è presente nel layout corrente, puoi utilizzare tools:viewBindingType
per impostare il tipo generato su NavigationBarView
in entrambi i layout:
# in res/layout/navigation_example.xml
<BottomNavigationView android:id="@+id/navigation" tools:viewBindingType="NavigationBarView" />
# in res/layout-w720/navigation_example.xml
<NavigationRailView android:id="@+id/navigation" tools:viewBindingType="NavigationBarView" />
Il binding delle visualizzazioni non può convalidare il valore di questo attributo durante la generazione del codice. Per evitare errori di compilazione e di runtime, il valore deve soddisfare le seguenti condizioni:
- Il valore deve essere una classe che eredita da
android.view.View
. Il valore deve essere un superclasse del tag in cui è inserito. Ad esempio, i seguenti valori non funzionano:
<TextView tools:viewBindingType="ImageView" /> <!-- ImageView is not related to TextView. --> <TextView tools:viewBindingType="Button" /> <!-- Button is not a superclass of TextView. -->
Il tipo finale deve essere risolto in modo coerente in tutte le configurazioni.
Differenze rispetto a findViewById
Il binding delle visualizzazioni presenta vantaggi importanti rispetto all'utilizzo di findViewById
:
- Sicurezza di null:poiché il binding delle visualizzazioni crea riferimenti diretti alle visualizzazioni, non c'è il rischio di un'eccezione di puntatore null a causa di un ID visualizzazione non valido.
Inoltre, quando una visualizzazione è presente solo in alcune configurazioni di un layout, il campo contenente il relativo riferimento nella classe di binding è contrassegnato con
@Nullable
. - Sicurezza del tipo:i campi di ogni classe di binding hanno tipi corrispondenti alle visualizzazioni a cui fanno riferimento nel file XML. Ciò significa che non c'è il rischio di un'eccezione di errato invio di un valore a un tipo.
Queste differenze comportano incompatibilità tra il layout e il codice, con conseguente fallimento della compilazione anziché del runtime.
Confronto con l'associazione di dati
Sia il binding delle visualizzazioni sia il binding dei dati generano classi di binding che puoi utilizzare per fare riferimento direttamente alle visualizzazioni. Tuttavia, il binding delle visualizzazioni è progettato per gestire casi d'uso più semplici e offre i seguenti vantaggi rispetto al binding dei dati:
- Compilazione più rapida: il binding delle visualizzazioni non richiede l'elaborazione delle annotazioni, pertanto i tempi di compilazione sono più rapidi.
- Facilità d'uso:il binding delle visualizzazioni non richiede file di layout XML con tag speciali, quindi è più veloce da adottare nelle app. Una volta attivata la associazione delle visualizzazioni in un modulo, questa viene applicata automaticamente a tutti i layout del modulo.
D'altra parte, il binding delle viste presenta le seguenti limitazioni rispetto al binding dei dati:
- Il binding delle visualizzazioni non supporta le variabili di layout o le espressioni di layout, pertanto non può essere utilizzato per dichiarare i contenuti dell'interfaccia utente dinamica direttamente dai file di layout XML.
- Il binding delle visualizzazioni non supporta il binding dei dati bidirezionale.
Per questi motivi, in alcuni casi è preferibile utilizzare sia il binding della vista sia il binding dei dati in un progetto. Puoi utilizzare il binding dei dati nei layout che richiedono funzionalità avanzate e il binding delle visualizzazioni nei layout che non lo richiedono.
Risorse aggiuntive
Per scoprire di più sul binding delle visualizzazioni, consulta le seguenti risorse aggiuntive:
Blog
Video
Consigliati per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Eseguire la migrazione da Kotlin Synthetics a Jetpack View Binding
- Layout ed espressioni di binding
- Architettura dell'app: livello UI - Inizia