Concetti e implementazione di Jetpack Compose
Questa pagina presenta diverse best practice e consigli per l'architettura. Adottali per migliorare la qualità, la robustezza e la scalabilità della tua app. Inoltre, semplificano la manutenzione e il test dell'app.
Livello UI
Il ruolo del livello UI è visualizzare i dati dell'applicazione sullo schermo e fungere da punto principale di interazione dell'utente. Ecco alcune best practice per il livello UI:
- Devi creare repository anche se contengono una sola origine dati.
- Nelle app di piccole dimensioni, puoi scegliere di inserire i tipi di livello dati in un pacchetto o modulo
data.
Consiglio |
Descrizione |
Segui il flusso di dati unidirezionale (UDF). Vivamente consigliato |
Segui i principi del flusso di dati unidirezionale (UDF), in cui i ViewModel espongono lo stato della UI utilizzando il pattern Observer e ricevono azioni dalla UI tramite chiamate di metodi. |
Utilizza AAC ViewModels se i relativi vantaggi si applicano alla tua app. Vivamente consigliato |
Utilizza AAC ViewModels per gestire la logica di business e recuperare i dati dell'applicazione per esporre lo stato dell'interfaccia utente all'interfaccia utente. Scopri altre best practice per ViewModel qui. Scopri i vantaggi di ViewModels qui. |
Utilizza la raccolta dello stato dell'interfaccia utente in base al ciclo di vita. Vivamente consigliato |
Raccogli lo stato della UI dalla UI utilizzando il builder di coroutine consapevole del ciclo di vita appropriato, Scopri di più su |
Non inviare eventi dalla ViewModel alla UI. Vivamente consigliato |
Elabora immediatamente l'evento nel ViewModel e causa un aggiornamento dello stato con il risultato della gestione dell'evento. Scopri di più sugli eventi dell'interfaccia utente qui. |
Utilizza un'applicazione con una sola attività. Consigliati |
Utilizza i frammenti di navigazione per spostarti tra le schermate e creare deep link alla tua app se ha più di una schermata. |
Il seguente snippet mostra come raccogliere lo stato della UI in modo consapevole del ciclo di vita:
class MyFragment : Fragment() {
private val viewModel: MyViewModel by viewModel()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect {
// Process item
}
}
}
}
}
ViewModel
Le ViewModel sono responsabili di fornire lo stato della UI e l'accesso al livello di dati. Di seguito sono riportate alcune best practice per i ViewModel:
Consiglio |
Descrizione |
I ViewModel devono essere indipendenti dal ciclo di vita di Android. Vivamente consigliato |
I ViewModel non devono contenere riferimenti a tipi correlati al ciclo di vita. Non trasmettere |
Utilizza coroutine e flussi. Vivamente consigliato |
ViewModel interagisce con i livelli di dati o di dominio utilizzando:
|
Utilizza ViewModels a livello di schermata. Vivamente consigliato |
Non utilizzare ViewModels in parti riutilizzabili dell'UI. Devi utilizzare i ViewModel in:
|
Non utilizzare Vivamente consigliato |
Utilizza la classe |
Esporre uno stato dell'interfaccia utente. Consigliati |
I ViewModel devono esporre i dati all'UI tramite una singola proprietà denominata
|
Lo snippet seguente mostra come esporre lo stato della UI da un ViewModel:
@HiltViewModel
class BookmarksViewModel @Inject constructor(
newsRepository: NewsRepository
) : ViewModel() {
val feedState: StateFlow<NewsFeedUiState> =
newsRepository
.getNewsResourcesStream()
.mapToFeedState(savedNewsResourcesState)
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = NewsFeedUiState.Loading
)
// ...
}
Ciclo di vita
Di seguito sono riportate alcune best practice per l'utilizzo del ciclo di vita di Android:
Consiglio |
Descrizione |
Non eseguire l'override dei metodi del ciclo di vita in Attività o Frammenti. Vivamente consigliato |
Non eseguire l'override dei metodi del ciclo di vita come |
Il seguente snippet descrive come eseguire le operazioni in base a un determinato stato del ciclo di vita:
class MyFragment: Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewLifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver {
override fun onResume(owner: LifecycleOwner) {
// ...
}
override fun onPause(owner: LifecycleOwner) {
// ...
}
}
}
}