Panoramica di ViewModel (visualizzazioni)
Concetti e implementazione di Jetpack Compose
La classe ViewModel è un contenitore di stato a livello di logica di business o schermata. Espone lo stato all'interfaccia utente e incapsula la logica di business correlata.
Il suo vantaggio principale è che memorizza nella cache lo stato e lo mantiene
durante le modifiche alla configurazione. Ciò significa che la tua UI non deve recuperare nuovamente i dati
quando passi da un'attività all'altra o quando segui le modifiche alla configurazione, ad esempio
quando ruoti lo schermo.
Vantaggi di ViewModel
L'alternativa a un ViewModel è una semplice classe che contiene i dati visualizzati nella UI. Questo può diventare un problema quando si passa da un'attività all'altra o alle destinazioni di navigazione. In questo modo i dati vengono eliminati se non li memorizzi utilizzando il meccanismo di stato dell'istanza salvato. ViewModel fornisce un'API comoda per la persistenza dei dati che risolve questo problema.
I vantaggi principali della classe ViewModel sono essenzialmente due:
- Consente di rendere persistente lo stato dell'interfaccia utente.
- Fornisce l'accesso alla logica di business.
Ambito
Quando crei un'istanza di un ViewModel, gli passi un oggetto che implementa l'interfaccia
ViewModelStoreOwner. Può trattarsi di una destinazione di navigazione,
di un grafico di navigazione, di un'attività, di un frammento o di qualsiasi altro tipo che implementi l'interfaccia. La ViewModel viene quindi limitata all'Lifecycle di
ViewModelStoreOwner. Rimane in memoria finché il suo ViewModelStoreOwner
non scompare definitivamente.
Una serie di classi sono sottoclassi dirette o indirette dell'interfaccia
ViewModelStoreOwner. Le sottoclassi dirette sono
ComponentActivity, Fragment e NavBackStackEntry.
Per un elenco completo delle sottoclassi indirette, consulta il
riferimento ViewModelStoreOwner.
Implementare un ViewModel
Di seguito è riportato un esempio di implementazione di un ViewModel per una schermata che consente all'utente di tirare i dadi.
Kotlin
data class DiceUiState(
val firstDieValue: Int? = null,
val secondDieValue: Int? = null,
val numberOfRolls: Int = 0,
)
class DiceRollViewModel : ViewModel() {
// Expose screen UI state
private val _uiState = MutableStateFlow(DiceUiState())
val uiState: StateFlow<DiceUiState> = _uiState.asStateFlow()
// Handle business logic
fun rollDice() {
_uiState.update { currentState ->
currentState.copy(
firstDieValue = Random.nextInt(from = 1, until = 7),
secondDieValue = Random.nextInt(from = 1, until = 7),
numberOfRolls = currentState.numberOfRolls + 1,
)
}
}
}
Java
public class DiceUiState {
private final Integer firstDieValue;
private final Integer secondDieValue;
private final int numberOfRolls;
// ...
}
public class DiceRollViewModel extends ViewModel {
private final MutableLiveData<DiceUiState> uiState =
new MutableLiveData(new DiceUiState(null, null, 0));
public LiveData<DiceUiState> getUiState() {
return uiState;
}
public void rollDice() {
Random random = new Random();
uiState.setValue(
new DiceUiState(
random.nextInt(7) + 1,
random.nextInt(7) + 1,
uiState.getValue().getNumberOfRolls() + 1
)
);
}
}
Puoi quindi accedere al ViewModel da un'attività nel seguente modo:
Kotlin
import androidx.activity.viewModels
class DiceRollActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// Create a ViewModel the first time the system calls an activity's onCreate() method.
// Re-created activities receive the same DiceRollViewModel instance created by the first activity.
// Use the 'by viewModels()' Kotlin property delegate
// from the activity-ktx artifact
val viewModel: DiceRollViewModel by viewModels()
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect {
// Update UI elements
}
}
}
}
}
Java
public class MyActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create a ViewModel the first time the system calls an activity's onCreate() method.
// Re-created activities receive the same MyViewModel instance created by the first activity.
DiceRollViewModel model = new ViewModelProvider(this).get(DiceRollViewModel.class);
model.getUiState().observe(this, uiState -> {
// update UI
});
}
}
Consigliati per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Utilizzare le coroutine Kotlin con componenti sensibili al ciclo di vita
- Salvare gli stati dell'interfaccia utente
- Caricare e visualizzare i dati impaginati