Visualizza associazione Parte di Android Jetpack.

L'associazione delle viste è una funzionalità che semplifica la scrittura di codice che interagisce con le viste. Una volta attivata l'associazione di viste in un modulo, viene generata una classe di associazione per ogni file di layout XML presente in quel modulo. Un'istanza di una classe di associazione contiene riferimenti diretti a tutte le viste con un ID nel layout corrispondente.

Nella maggior parte dei casi, l'associazione di viste sostituisce findViewById.

Configurazione

L'associazione delle visualizzazioni viene attivata modulo per modulo. Per abilitare l'associazione della visualizzazione in un modulo, imposta l'opzione di build viewBinding su true nel file build.gradle a livello di modulo, come mostrato nell'esempio seguente:

Trendy

android {
    ...
    buildFeatures {
        viewBinding true
    }
}

Kotlin

android {
    ...
    buildFeatures {
        viewBinding = true
    }
}

Se vuoi che un file di layout venga ignorato durante la generazione di classi di associazione, aggiungi l'attributo tools:viewBindingIgnore="true" alla visualizzazione principale del file di layout:

<LinearLayout
        ...
        tools:viewBindingIgnore="true" >
    ...
</LinearLayout>

Utilizzo

Se per un modulo è abilitata l'associazione della vista, viene generata una classe di associazione per ogni file di layout XML contenuto nel modulo. Ogni classe di associazione contiene riferimenti alla vista principale e a tutte le viste che hanno un ID. Il nome della classe di associazione viene generato convertendo il nome del file XML in formato Pascal 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 associazione generata è denominata ResultProfileBinding. Questa classe ha due campi: un TextView chiamato name e un Button chiamato button. L'elemento ImageView nel layout non ha un ID, quindi non vi è alcun riferimento nella classe di associazione.

Ogni classe di associazione include anche un metodo getRoot(), che fornisce un riferimento diretto per la vista principale del file di layout corrispondente. In questo esempio, il metodo getRoot() nella classe ResultProfileBinding restituisce la vista principale LinearLayout.

Le seguenti sezioni mostrano l'utilizzo delle classi di associazione generate nelle attività e nei frammenti.

Utilizza l'associazione di visualizzazioni nelle attività

Per configurare un'istanza della classe di associazione da utilizzare con un'attività, esegui i passaggi seguenti nel metodo onCreate() dell'attività:

  1. Richiama il metodo inflate() statico incluso nella classe di associazione generata. Viene creata un'istanza della classe di associazione per l'attività.
  2. Ottieni un riferimento alla vista principale chiamando il metodo getRoot() o utilizzando la sintassi della proprietà Kotlin.
  3. Passa la vista principale a setContentView() per renderla attiva sullo schermo.

Questi passaggi sono mostrati 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 associazione per fare riferimento a qualsiasi vista:

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

Utilizza l'associazione Visualizza nei frammenti

Per configurare un'istanza della classe di associazione da utilizzare con un frammento, esegui i passaggi seguenti nel metodo onCreateView() del frammento:

  1. Richiama il metodo inflate() statico incluso nella classe di associazione generata. Viene creata un'istanza della classe di associazione per il frammento da utilizzare.
  2. Ottieni un riferimento alla vista principale chiamando il metodo getRoot() o utilizzando la sintassi della proprietà Kotlin.
  3. Ripristina la vista principale dal metodo onCreateView() per renderla 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 associazione per fare riferimento a qualsiasi vista:

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 le diverse configurazioni

Quando dichiari le viste in più configurazioni, a volte risulta utile utilizzare un tipo di visualizzazione diverso a seconda del layout specifico. Lo snippet di codice riportato di seguito mostra un esempio di ciò:

# 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, ci si potrebbe aspettare 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 codici di associazione delle viste non è in grado di determinarlo e genera invece un campo View. Questa operazione richiede la trasmissione del campo in un secondo momento con binding.userBio as TextView.

Per ovviare a questo limite, l'associazione della vista supporta un attributo tools:viewBindingType, che ti consente di indicare al compilatore quale tipo 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, supponi di avere due layout, uno contenente BottomNavigationView e un altro contenente un elemento NavigationRailView. Entrambe le classi estendono NavigationBarView, che contiene la maggior parte dei dettagli di implementazione. Se il tuo codice non ha bisogno di 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" />

L'associazione della vista non può convalidare il valore di questo attributo durante la generazione del codice. Per evitare errori in fase 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 una 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. -->
    
  • L'ultimo tipo deve risolvere in modo coerente in tutte le configurazioni.

Differenze rispetto a findViewById

L'associazione della vista offre importanti vantaggi rispetto all'uso di findViewById:

  • Sicurezza null: poiché l'associazione di viste crea riferimenti diretti alle viste, non c'è alcun rischio di un'eccezione di puntatore nullo a causa di un ID vista non valido. Inoltre, quando una vista è presente solo in alcune configurazioni di un layout, il campo contenente il riferimento nella classe di associazione è contrassegnato con @Nullable.
  • Tipo di sicurezza: i campi di ogni classe di associazione hanno un tipo corrispondente alle viste a cui fanno riferimento nel file XML. Ciò significa che non c'è alcun rischio di un'eccezione di classe Cast.

Queste differenze indicano incompatibilità tra il layout e il codice, che causano errori della build in fase di compilazione anziché in fase di runtime.

Confronto con l'associazione di dati

L'associazione di viste e l'associazione di dati generano entrambe classi di associazione che puoi utilizzare per fare riferimento direttamente alle viste. Tuttavia, l'associazione delle viste è pensata per gestire casi d'uso più semplici e offre i seguenti vantaggi rispetto all'associazione di dati:

  • Compilazione più rapida: l'associazione delle visualizzazioni non richiede l'elaborazione delle annotazioni, pertanto i tempi di compilazione sono più rapidi.
  • Facilità di utilizzo:l'associazione delle visualizzazioni non richiede file di layout XML con tag speciali, perciò è più veloce da adottare nelle app. Una volta abilitata, l'associazione della vista in un modulo viene applicata automaticamente a tutti i layout di quel modulo.

L'associazione vista, invece, presenta le seguenti limitazioni rispetto all'associazione dati:

A causa di queste considerazioni, in alcuni casi è preferibile utilizzare sia l'associazione di viste sia l'associazione di dati in un progetto. Puoi utilizzare l'associazione di dati nei layout che richiedono funzionalità avanzate e per quelli che non lo richiedono.

Risorse aggiuntive

Per scoprire di più sull'associazione delle viste, consulta le seguenti risorse aggiuntive:

Samples

Blog

Video