Kotlin-Koroutinen bieten eine API, mit der Sie asynchronen Code schreiben können. Mit Kotlin-Koroutinen können Sie einen CoroutineScope definieren, mit dem Sie festlegen können, wann Ihre Koroutinen ausgeführt werden sollen. Jeder asynchrone Vorgang wird in einem bestimmten Bereich ausgeführt.
Lebenszyklusbewusste Komponenten bieten erstklassige Unterstützung für Koroutinen für logische Bereiche in Ihrer App. In diesem Dokument wird erläutert, wie Sie Koroutinen effektiv mit lebenszyklusbewussten Komponenten verwenden.
Abhängigkeiten hinzufügen
Die in diesem Thema beschriebenen integrierten Koroutinenbereiche sind in der Lifecycle API enthalten. Achten Sie darauf, die entsprechenden Abhängigkeiten hinzuzufügen, wenn Sie diese Bereiche verwenden.
- Verwenden Sie für ViewModel-Dienstprogramme in Compose
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version"). - Verwenden Sie für Lebenszyklus-Dienstprogramme in Compose
implementation("androidx.lifecycle:lifecycle-runtime-compose:$lifecycle_version").
Lebenszyklusbewusste Koroutinenbereiche
Compose und die Lifecycle-Bibliotheken bieten die folgenden integrierten Bereiche, die Sie in Ihrer App verwenden können.
ViewModelScope
Für jedes ViewModel in Ihrer App wird ein ViewModelScope definiert. Jede in diesem Bereich gestartete Koroutine wird automatisch abgebrochen, wenn das ViewModel gelöscht wird. Koroutinen sind hier nützlich, wenn Sie Aufgaben haben, die nur ausgeführt werden müssen, wenn die ViewModel aktiv ist. Wenn Sie beispielsweise Daten für ein Layout berechnen, sollten Sie den Bereich der Arbeit auf die ViewModel beschränken, damit die Arbeit automatisch abgebrochen wird, wenn die ViewModel gelöscht wird, um Ressourcen zu sparen.
Sie können auf die CoroutineScope einer ViewModel über das Attribut viewModelScope der ViewModel zugreifen, wie im folgenden Beispiel gezeigt:
class MyViewModel: ViewModel() {
init {
viewModelScope.launch {
// Coroutine that will be canceled when the ViewModel is cleared.
}
}
}
Für komplexere Anwendungsfälle können Sie einen benutzerdefinierten CoroutineScope direkt an den Konstruktor des ViewModels übergeben, um den Standard-viewModelScope zu ersetzen. Dieser Ansatz bietet mehr Kontrolle und Flexibilität, insbesondere für:
Testen: Sie können einen
TestScopeeinfügen, um die Zeit zu steuern und das Verhalten von Koroutinen in Unit-Tests zu prüfen.Benutzerdefinierte Konfiguration: Sie können den Bereich mit einem bestimmten
CoroutineDispatcher(z. B.Dispatchers.Defaultfür rechenintensive Aufgaben) oder einem benutzerdefiniertenCoroutineExceptionHandlerkonfigurieren, bevor das ViewModel überhaupt mit der Arbeit beginnt.
Kompositionsgebundene Bereiche
Nebenwirkungen wie Animationen, Netzwerkaufrufe oder Timer müssen auf den Lebenszyklus der zusammensetzbaren Funktion beschränkt sein. Wenn eine komponierbare Funktion den Bildschirm verlässt (die Komposition verlässt), werden alle laufenden Koroutinen automatisch abgebrochen, um Speicherlecks zu vermeiden.
Compose bietet die API LaunchedEffect, um den Gültigkeitsbereich der Composition deklarativ zu verwalten.
LaunchedEffect erstellt einen CoroutineScope, mit dem Sie Sperrfunktionen ausführen können. Der Bereich ist an den Kompositionslebenszyklus der zusammensetzbaren Funktion gebunden, nicht an den Lebenszyklus der Hostaktivität.
- Eingabe: Die Koroutine wird gestartet, wenn die komponierbare Funktion in die Komposition eintritt.
- Beenden: Die Koroutine wird abgebrochen, wenn das Composable die Komposition verlässt.
- Neustart: Wenn sich ein an
LaunchedEffectübergebener Schlüssel ändert, wird die vorhandene Koroutine abgebrochen und eine neue gestartet.
Im folgenden Beispiel wird gezeigt, wie Sie mit LaunchedEffect eine pulsierende Animation erstellen. Die Koroutine ist an das Vorhandensein des Composeables in der Komposition gebunden und reagiert auf Konfigurationsänderungen:
// Allow the pulse rate to be configured, so it can be sped up if the user is running // out of time var pulseRateMs by remember { mutableLongStateOf(3000L) } val alpha = remember { Animatable(1f) } LaunchedEffect(pulseRateMs) { // Restart the effect when the pulse rate changes while (isActive) { delay(pulseRateMs) // Pulse the alpha every pulseRateMs to alert the user alpha.animateTo(0f) alpha.animateTo(1f) } }
Weitere Informationen zu LaunchedEffect finden Sie unter Nebenwirkungen in Compose.
Lebenszyklusbewusste Ablaufsammlung
Verwenden Sie die collectAsStateWithLifecycle API, um Abläufe in Jetpack Compose sicher zu erfassen. Diese einzelne Funktion wandelt einen Flow in ein Compose-State-Objekt um und verwaltet automatisch das Lebenszyklus-Abo für Sie. Standardmäßig beginnt die Erfassung, wenn der Lebenszyklus STARTED ist, und endet, wenn der Lebenszyklus STOPPED ist. Wenn Sie dieses Standardverhalten überschreiben möchten, übergeben Sie den Parameter minActiveState mit der gewünschten Lebenszyklusmethode, z. B. Lifecycle.State.RESUMED.
Das folgende Beispiel zeigt, wie Sie den StateFlow eines ViewModels in einer zusammensetzbaren Funktion erfassen:
@Composable private fun ConversationScreen( conversationViewModel: ConversationViewModel = viewModel() ) { val messages by conversationViewModel.messages.collectAsStateWithLifecycle() ConversationScreen( messages = messages, onSendMessage = { message: Message -> conversationViewModel.sendMessage(message) } ) } @Composable private fun ConversationScreen( messages: List<Message>, onSendMessage: (Message) -> Unit ) { MessagesList(messages, onSendMessage) /* ... */ }
Parallele Erfassung mehrerer Abläufe
In Compose können Sie mehrere Abläufe parallel erfassen, indem Sie mehrere Statusvariablen deklarieren. Da collectAsStateWithLifecycle seinen eigenen zugrunde liegenden Bereich verwaltet, wird die parallele Erfassung automatisch verarbeitet:
@Composable
fun DashboardScreen(viewModel: DashboardViewModel = viewModel()) {
// Both flows are collected safely in parallel and will emit updates when either changes, the composables will recompose
val userData by viewModel.userFlow.collectAsStateWithLifecycle()
val feedData by viewModel.feedFlow.collectAsStateWithLifecycle()
// ...
}
Werte asynchron mit Flows berechnen
Wenn Sie Werte asynchron berechnen müssen, verwenden Sie StateFlow mit dem Operator stateIn.
Im folgenden Snippet wird ein Standard-Flow verwendet, der in einen StateFlow konvertiert wurde. Mit dem Parameter WhileSubscribed(5000) bleibt das Abo fünf Sekunden lang aktiv, nachdem die Benutzeroberfläche ausgeblendet wurde, um Konfigurationsänderungen zu verarbeiten.
val uiState: StateFlow<Result> = flow {
emit(repository.fetchData())
}
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = Result.Loading
)
Verwenden Sie collectAsStateWithLifecycle, um die erfassten Werte in Compose-State zu konvertieren, damit die Benutzeroberfläche bei Datenänderungen reaktiv aktualisiert werden kann.
Weitere Informationen zum Status finden Sie unter Status und Jetpack Compose.
Zusätzliche Ressourcen
Inhalte ansehen
Beispiele
Empfehlungen für Sie
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Lebenszyklen mit lebenszyklusorientierten Komponenten verwalten
- Seitenweise Daten laden und anzeigen