Questo codelab fa parte del corso Android Kotlin Fundamentals. Otterrai il massimo valore da questo corso se lavori in sequenza nei codelab. Tutti i codelab del corso sono elencati nella pagina di destinazione di Android Kotlin Fundamentals.
Introduzione
Nei codelab precedenti di questo corso, hai utilizzato la funzione findViewById()
per ottenere riferimenti alle viste. Se la tua app ha gerarchie di visualizzazioni complesse, findViewById()
è costosa e rallenta. Android attraversa la gerarchia di visualizzazione, a partire dalla radice, finché non trova la vista desiderata. Fortunatamente, c'è un modo migliore.
Per impostare i dati nelle viste, hai utilizzato risorse di tipo stringa e hai impostato i dati dell'attività. Sarebbe più efficiente se la vista sapesse dei dati. Per fortuna, è tutto possibile.
In questo codelab, imparerai a utilizzare l'associazione di dati per eliminare la necessità di findViewById()
. Imparerai anche a utilizzare l'associazione di dati per accedere ai dati direttamente da una vista.
Informazioni importanti
Dovresti acquisire familiarità con:
- Che cos'è un'attività e come configurarla con un layout in
onCreate()
. - Creazione di una visualizzazione di testo e impostazione del testo visualizzato.
- Utilizzare
findViewById()
per ottenere un riferimento a una vista. - Creazione e modifica di un layout XML di base per una vista.
Obiettivi didattici
- Come utilizzare la libreria di associazione di dati per eliminare le chiamate inefficienti verso
findViewById()
. - Come accedere ai dati delle app direttamente da XML.
In questo lab proverai a:
- Modifica un'app in modo che utilizzi l'associazione di dati invece di
findViewById()
per accedere ai dati direttamente dai file XML di layout.
In questo codelab, inizierai dall'app Informazioni su me e cambi l'app in modo che utilizzi l'associazione di dati. L'app avrà esattamente lo stesso aspetto al termine dell'operazione.
Ecco cosa fa l'app Informazioni su di me:
- Quando l'utente apre l'app, l'app mostra un nome, un campo per inserire un nickname, un pulsante Fine, un'immagine a stella e testo scorrevole.
- L'utente può inserire un nickname e toccare il pulsante Fine. Il campo e il pulsante modificabili sono sostituiti da una visualizzazione di testo che mostra il nickname inserito.
Puoi utilizzare il codice creato nel codelab precedente oppure scaricare il codice AboutMeDataBinding-Starter da GitHub.
Il codice che hai scritto nei codelab precedenti utilizza la funzione findViewById()
per ottenere riferimenti alle viste.
Ogni volta che utilizzi findViewById()
per cercare una vista dopo averla creata o ricreata, il sistema Android attraversa la gerarchia di visualizzazioni al momento dell'esecuzione. Anche se la tua app ha solo poche visualizzazioni, non è un problema. Tuttavia, le app di produzione potrebbero avere decine di visualizzazioni in un layout e, anche con il design migliore, ci saranno viste nidificate.
Pensa a un layout lineare che contiene una visualizzazione di scorrimento che contiene una visualizzazione di testo. Nel caso di una gerarchia di visualizzazione grande o profonda, trovare una visualizzazione può richiedere tempo tale da rallentare notevolmente l'app per l'utente. La memorizzazione delle variabili nella cache può essere utile, ma devi comunque inizializzare una variabile per ogni vista in ogni spazio dei nomi. Con molte visualizzazioni e diverse attività, tutto questo si aggiunge.
Una soluzione è creare un oggetto contenente un riferimento a ogni vista. Questo oggetto, chiamato oggetto Binding
, può essere utilizzato dall'intera app. Questa tecnica è chiamata associazione di dati. Dopo aver creato un oggetto di associazione per la tua app, puoi accedere alle viste e ad altri dati tramite l'oggetto di associazione, senza dover attraversare la gerarchia delle visualizzazioni o cercare i dati.
L'associazione di dati offre i seguenti vantaggi:
- Il codice è più breve, più facile da leggere e più facile da gestire rispetto a quello che utilizza
findByView()
. - I dati e le viste sono separati chiaramente. Questo vantaggio legato all'associazione di dati diventa sempre più importante alla fine di questo corso.
- Il sistema Android attraversa la gerarchia di visualizzazione solo una volta per ottenere ogni visualizzazione e si verifica durante l'avvio dell'app, non in fase di runtime quando l'utente interagisce con l'app.
- Hai sicurezza del tipo per accedere alle viste. Con Sicurezza del tipo, il compilatore convalida i tipi durante la compilazione e genera un errore se tenti di assegnare il tipo sbagliato a una variabile.
In questa attività devi configurare l'associazione di dati e utilizzare l'associazione di dati per sostituire le chiamate a findViewById()
con le chiamate all'oggetto di associazione.
Passaggio 1: attiva l'associazione di dati
Per utilizzare l'associazione di dati, devi attivare l'associazione di dati nel tuo file Gradle, in quanto non è abilitata per impostazione predefinita. Questo perché l'associazione di dati aumenta il tempo di compilazione e potrebbe influire sul tempo di avvio dell'app.
- Se non hai l'app Informazioni su un codelab precedente, recupera il codice AboutMeDataBinding-Starter di GitHub. Aprilo in Android Studio.
- Apri il file
build.gradle (Module: app)
. - All'interno della sezione
android
, prima della parentesi di chiusura, aggiungi una sezionedataBinding
e impostaenabled
sutrue
.
dataBinding {
enabled = true
}
- Quando richiesto, sincronizza il progetto. Se non ti viene richiesto, seleziona File > Sync Project with Gradle Files.
- Puoi eseguire l'app, ma non noterai cambiamenti.
Passaggio 2: modifica il file di layout in modo che sia utilizzabile con l'associazione di dati
Per utilizzare l'associazione di dati, devi aggregare il layout XML a un tag <layout>
. In questo modo la classe principale non è più un gruppo di viste, ma è un layout che contiene gruppi di viste e viste. L'oggetto vincolante può quindi conoscere il layout e le viste al suo interno.
- Apri il file
activity_main.xml
. - Passa alla scheda Testo.
- Aggiungi
<layout></layout>
come tag più esterno attorno a<LinearLayout>
.
<layout>
<LinearLayout ... >
...
</LinearLayout>
</layout>
- Scegli Codice &Riformatta il codice per correggere il rientro del codice.
Le dichiarazioni dello spazio dei nomi per un layout devono essere nel tag più esterno.
- Taglia le dichiarazioni dello spazio dei nomi da
<LinearLayout>
e incollale nel tag<layout>
. Il tag di apertura<layout>
dovrebbe apparire come mostrato di seguito, mentre il tag<LinearLayout>
deve contenere solo proprietà di visualizzazione.
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
- Crea ed esegui la tua app per verificare di averlo fatto correttamente.
Passaggio 3: crea un oggetto vincolante nell'attività principale
Aggiungi un riferimento all'oggetto binding all'attività principale, in modo da poterlo utilizzare per accedere alle viste:
- Apri il file
MainActivity.kt
. - Prima del giorno
onCreate()
, al livello superiore, crea una variabile per l'oggetto binding. Questa variabile è in genere denominatabinding
.
Il tipo dibinding
, la classeActivityMainBinding
, viene creato dal compilatore appositamente per questa attività principale. Il nome deriva dal nome del file di layout, ovveroactivity_main + Binding
.
private lateinit var binding: ActivityMainBinding
- Se richiesto da Android Studio, importa
ActivityMainBinding
. Se non ti viene richiesto, fai clic suActivityMainBinding
e premiAlt+Enter
(Option+Enter
su Mac) per importare il corso mancante. Per ulteriori scorciatoie da tastiera, consulta Scorciatoie da tastiera.
L'istruzioneimport
dovrebbe essere simile a quella mostrata di seguito.
import com.example.android.aboutme.databinding.ActivityMainBinding
Successivamente, sostituisci la funzione setContentView()
corrente con un'istruzione che esegue le seguenti operazioni:
- Crea l'oggetto di associazione.
- Utilizza la funzione
setContentView()
della classeDataBindingUtil
per associare il layoutactivity_main
aMainActivity
. Questa funzionesetContentView()
si occupa anche di alcune configurazioni di associazione di dati per le viste.
- In
onCreate()
, sostituisci la chiamatasetContentView()
con la seguente riga di codice.
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
- Importa
DataBindingUtil
.
import androidx.databinding.DataBindingUtil
Passaggio 4: utilizza l'oggetto binding per sostituire tutte le chiamate afindViewById()
Ora puoi sostituire tutte le chiamate a findViewById()
con i riferimenti alle viste presenti nell'oggetto binding. Quando viene creato l'oggetto di associazione, il compilatore genera i nomi delle viste nell'oggetto di associazione dagli ID delle viste nel layout, convertendoli in lettere maiuscole. Quindi, ad esempio, done_button
è doneButton
nell'oggetto binding, nickname_edit
diventa nicknameEdit
e nickname_text
diventa nicknameText
.
- In
onCreate()
, sostituisci il codice che utilizzafindViewById()
per trovare l'elementodone_button
con il codice che fa riferimento al pulsante nell'oggetto di associazione.
Sostituisci questo codice:findViewById<Button>(R.id.
done_button
)
con:binding.doneButton
Il codice completo per impostare il listener di clic inonCreate()
dovrebbe avere questo aspetto.
binding.doneButton.setOnClickListener {
addNickname(it)
}
- Ripeti l'operazione per tutte le chiamate a
findViewById()
nella funzioneaddNickname()
.
Sostituisci tutte le occorrenze difindViewById<
View
>(R.id.
id_view
)
conbinding.
idView
. Esegui questa operazione nel seguente modo:
- Elimina le definizioni delle variabili
editText
enicknameTextView
insieme alle relative chiamate afindViewById()
. Verranno visualizzati errori. - Correggi gli errori recuperando le visualizzazioni
nicknameText
,nicknameEdit
edoneButton
dall'oggettobinding
anziché le variabili (eliminate). - Sostituisci
view.visibility
conbinding.doneButton.visibility
. Se utilizzibinding.doneButton
invece diview
, il codice diventa più coerente.
Il risultato è il seguente codice:
binding.nicknameText.text = binding.nicknameEdit.text
binding.nicknameEdit.visibility = View.GONE
binding.doneButton.visibility = View.GONE
binding.nicknameText.visibility = View.VISIBLE
- Le funzionalità non subiranno modifiche. Facoltativamente, ora puoi eliminare il parametro
view
e aggiornare tutti gli utilizzi diview
in modo che utilizzinobinding.doneButton
all'interno di questa funzione.
nicknameText
richiede unString
enicknameEdit.text
è unEditable
. Quando utilizzi l'associazione di dati, devi convertire esplicitamenteEditable
in unString
.
binding.nicknameText.text = binding.nicknameEdit.text.toString()
- Puoi eliminare le importazioni non selezionabili.
- Kotlinizza la funzione utilizzando
apply{}
.
binding.apply {
nicknameText.text = nicknameEdit.text.toString()
nicknameEdit.visibility = View.GONE
doneButton.visibility = View.GONE
nicknameText.visibility = View.VISIBLE
}
- Crea ed esegui la tua app: l'aspetto dovrebbe essere lo stesso di prima.
Puoi utilizzare l'associazione di dati per rendere una classe di dati direttamente disponibile per una vista. Questa tecnica semplifica il codice ed è molto utile per la gestione di richieste più complesse.
Per questo esempio, invece di impostare il nome e il nickname utilizzando le risorse stringa, crei una classe dati per il nome e il nickname. La classe dati diventa disponibile per la vista utilizzando l'associazione di dati.
Passaggio 1: crea la classe di dati MyName
- In Android Studio nella directory
java
, apri il fileMyName.kt
. Se non hai questo file, crea un nuovo file Kotlin e chiamaloMyName.kt
. - Definisci una classe di dati per il nome e il nickname. Utilizza le stringhe vuote come valori predefiniti.
data class MyName(var name: String = "", var nickname: String = "")
Passaggio 2: aggiungi dati al layout
Nel file activity_main.xml
, il nome è attualmente impostato in un elemento TextView
di una risorsa stringa. Devi sostituire il riferimento al nome con un riferimento ai dati nella classe dati.
- Apri
activity_main.xml
nella scheda Testo. - Nella parte superiore del layout, tra i tag
<layout>
e<LinearLayout>
, inserisci un tag<data></data>
. Qui colleghi la vista ai dati.
<data>
</data>
All'interno dei tag dei dati, puoi dichiarare le variabili denominate che contengono un riferimento a una classe.
- All'interno del tag
<data>
, aggiungi un tag<variable>
. - Aggiungi un parametro
name
per assegnare alla variabile un nome"myName"
. Aggiungi un parametrotype
e imposta il tipo su un nome completo della classe di datiMyName
(nome pacchetto + nome variabile).
<variable
name="myName"
type="com.example.android.aboutme.MyName" />
Ora, invece di utilizzare la risorsa stringa per il nome, puoi fare riferimento alla variabile myName
.
- Sostituisci
android:text="@string/name"
con il codice riportato di seguito.
@={}
è un'istruzione per recuperare i dati a cui viene fatto riferimento all'interno delle parentesi graffe.
myName
fa riferimento alla variabile myName
definita in precedenza, che rimanda alla classe dei dati myName
e recupera la proprietà name
dalla classe.
android:text="@={myName.name}"
Passaggio 3: crea i dati
Ora puoi fare riferimento ai dati nel tuo file di layout. Il passaggio successivo consiste nel creare i dati effettivi.
- Apri il file
MainActivity.kt
. - Sopra
onCreate()
, crea una variabile privata, chiamata anchemyName
per convenzione. Assegna alla variabile un'istanza della classe datiMyName
, trasmettendo il nome.
private val myName: MyName = MyName("Aleks Haecky")
- In
onCreate()
, imposta il valore della variabilemyName
nel file di layout sul valore della variabilemyName
appena dichiarato. Non puoi accedere direttamente alla variabile nel file XML. È necessario accedervi tramite l'oggetto binding.
binding.myName = myName
- Questo potrebbe causare un errore perché è necessario aggiornare l'oggetto binding dopo aver apportato modifiche. Crea la tua app e l'errore dovrebbe scomparire.
Passaggio 4: utilizza la classe di dati per il nickname in TextView
Il passaggio finale consiste nell'utilizzare la classe dei dati per il nickname in TextView
.
- Apri
activity_main.xml
. - Aggiungi una proprietà
text
nella visualizzazione di testonickname_text
. Fai riferimento all'elementonickname
nella classe dei dati, come mostrato di seguito.
android:text="@={myName.nickname}"
- In
ActivityMain
, sostituiscinicknameText.text = nicknameEdit.text.toString()
con il codice per impostare il nickname nella variabilemyName
.
myName?.nickname = nicknameEdit.text.toString()
Dopo aver impostato il nickname, vuoi che il codice aggiorni l'interfaccia utente con i nuovi dati. Per farlo, devi annullare tutte le espressioni di associazione in modo che vengano ricreate con i dati corretti.
- Aggiungi
invalidateAll()
dopo aver impostato il nickname in modo che l'interfaccia utente venga aggiornata con il valore dell'oggetto binding aggiornato.
binding.apply {
myName?.nickname = nicknameEdit.text.toString()
invalidateAll()
...
}
- Crea ed esegui la tua app, che dovrebbe funzionare esattamente come prima.
Progetto Android Studio: AboutMeDataBinding
Per utilizzare l'associazione di dati per sostituire le chiamate con findViewById()
:
- Attiva l'associazione di dati nella sezione Android del file
build.gradle
:dataBinding { enabled = true }
- Utilizza
<layout>
come visualizzazione principale nel layout XML. - Definisci una variabile di associazione:
private lateinit var binding: ActivityMainBinding
- Crea un oggetto vincolante in
MainActivity
sostituendosetContentView
:binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
- Sostituisci le chiamate a
findViewById()
con riferimenti alla vista nell'oggetto vincolante. Ad esempio:findViewById<Button>(R.id.done_button) ⇒ binding.doneBu
tton
(in questo esempio, il nome della vista è generato nel formato cammello della vistaid
della vista nel file XML.)
Passaggi per associare le viste ai dati:
- Crea una classe per i tuoi dati.
- Aggiungi un blocco
<data>
all'interno del tag<layout>
. - Definisci un
<variable>
con un nome e un tipo che sia la classe dei dati.
<data>
<variable
name="myName"
type="com.example.android.aboutme.MyName" />
</data>
- In
MainActivity
, crea una variabile con un'istanza della classe di dati. Ad esempio:private val myName: MyName = MyName("Aleks Haecky")
- Nell'oggetto binding, imposta la variabile su quella appena creata:
binding.myName = myName
- Nel file XML, imposta i contenuti della vista sulla variabile che hai definito nel blocco
<data>
. Utilizza la notazione dei punti per accedere ai dati all'interno della classe dati.android:text="@={myName.name}"
Corso Udacity:
Documentazione per gli sviluppatori Android:
- Libreria di associazione di dati
- Classi di associazione generate
- Inizia a utilizzare l'associazione di dati
- Layout ed espressioni di associazione
In questa sezione sono elencati i possibili compiti per gli studenti che lavorano attraverso questo codelab nell'ambito di un corso tenuto da un insegnante. Spetta all'insegnante fare quanto segue:
- Assegna i compiti, se necessario.
- Comunica agli studenti come inviare compiti.
- Valuta i compiti.
Gli insegnanti possono utilizzare i suggerimenti solo quanto e come vogliono e dovrebbero assegnare i compiti che ritengono appropriati.
Se stai lavorando da solo a questo codelab, puoi utilizzare questi compiti per mettere alla prova le tue conoscenze.
Rispondi a queste domande
Domanda 1
Perché vuoi ridurre al minimo le chiamate esplicite e implicite a findViewById()
?
- Ogni volta che viene chiamato,
findViewById()
attraversa la gerarchia di visualizzazioni. findViewById()
viene eseguito sul thread principale o sull'interfaccia utente.- Queste chiamate possono rallentare l'interfaccia utente.
- La tua app ha meno probabilità di arrestarsi in modo anomalo.
Domanda 2
Come descriveresti l'associazione di dati?
Ad esempio, ecco alcune informazioni che potresti fornire in merito all'associazione di dati:
- La grande idea dell'associazione di dati consiste nel creare un oggetto che permetta di collegare/mappare/vincolare due informazioni lontane tra loro al momento della compilazione, in modo da non dover cercare i dati in fase di esecuzione.
- L'oggetto che mostra queste associazioni è chiamato oggetto collegamento.
- L'oggetto di associazione viene creato dal compilatore.
Domanda 3
Quale dei seguenti NON è un vantaggio dell'associazione di dati?
- Il codice è più breve, più facile da leggere e da gestire.
- I dati e le viste sono separati chiaramente.
- Il sistema Android attraversa la gerarchia di visualizzazioni solo una volta per ottenere ogni visualizzazione.
- La chiamata a
findViewById()
genera un errore di compilazione. - Digita sicurezza per l'accesso alle viste.
Domanda 4
Qual è la funzione del tag <layout>
?
- Arrotolalo intorno alla visualizzazione principale nel layout.
- Le associazioni vengono create per tutte le viste di un layout.
- Indica la visualizzazione di primo livello in un layout XML che utilizza l'associazione di dati.
- Puoi utilizzare il tag
<data>
all'interno di un elemento<layout>
per associare una variabile a una classe di dati.
Domanda 5
Qual è il modo corretto per fare riferimento ai dati associati nel layout XML?
android:text="@={myDataClass.property}"
android:text="@={myDataClass}"
android:text="@={myDataClass.property.toString()}"
android:text="@={myDataClass.bound_data.property}"
Inizia la lezione successiva:
Per i link ad altri codelab in questo corso, consulta la pagina di destinazione di Android Kotlin Fundamentals.