ViewModel – Übersicht (Views)
Konzepte und Jetpack Compose-Implementierung
Die Klasse ViewModel ist ein State Holder auf Geschäftslogik- oder Bildschirmebene. Sie stellt den Status für die Benutzeroberfläche bereit und kapselt die zugehörige Geschäftslogik.
Der Hauptvorteil besteht darin, dass der Status im Cache gespeichert und bei Konfigurationsänderungen beibehalten wird. Das bedeutet, dass Ihre Benutzeroberfläche beim Wechseln zwischen Aktivitäten oder nach Konfigurationsänderungen, z. B. beim Drehen des Bildschirms, keine Daten mehr abrufen muss.
Vorteile von ViewModels
Die Alternative zu einem ViewModel ist eine einfache Klasse, die die Daten enthält, die Sie in Ihrer Benutzeroberfläche anzeigen. Das kann zu Problemen führen, wenn Sie zwischen Aktivitäten oder Navigationszielen wechseln. Dadurch werden diese Daten zerstört, wenn Sie sie nicht mit dem Mechanismus für den gespeicherten Instanzstatus speichern. ViewModel bietet eine praktische API für die Datenpersistenz, mit der dieses Problem behoben wird.
Die wichtigsten Vorteile der ViewModel-Klasse sind im Wesentlichen zwei:
- Damit können Sie den UI-Status beibehalten.
- Sie bietet Zugriff auf die Geschäftslogik.
Umfang
Wenn Sie ein ViewModel instanziieren, übergeben Sie ihm ein Objekt, das die ViewModelStoreOwner-Schnittstelle implementiert. Das kann ein Navigationsziel, ein Navigationsdiagramm, eine Aktivität, ein Fragment oder ein anderer Typ sein, der die Schnittstelle implementiert. Ihr ViewModel ist dann auf den Lifecycle des ViewModelStoreOwner beschränkt. Sie bleibt im Arbeitsspeicher, bis die ViewModelStoreOwner endgültig entfernt wird.
Eine Reihe von Klassen sind entweder direkte oder indirekte Unterklassen der ViewModelStoreOwner-Schnittstelle. Die direkten Unterklassen sind ComponentActivity, Fragment und NavBackStackEntry.
Eine vollständige Liste der indirekten Unterklassen finden Sie in der ViewModelStoreOwner-Referenz.
ViewModel implementieren
Das Folgende ist ein Beispiel für die Implementierung eines ViewModel für einen Bildschirm, auf dem der Nutzer würfeln kann.
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
)
);
}
}
Sie können dann so auf das ViewModel aus einer Aktivität zugreifen:
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
});
}
}
Empfehlungen für Sie
- Hinweis: Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Kotlin-Koroutinen mit lebenszyklusbewussten Komponenten verwenden
- UI-Zustände speichern
- Paginierte Daten laden und anzeigen