Coroutine Kotlin menyediakan API yang memungkinkan Anda menulis kode asinkron. Dengan coroutine Kotlin, Anda dapat menentukan CoroutineScope, yang
membantu Anda mengelola kapan coroutine harus dijalankan. Setiap operasi asinkron berjalan dalam cakupan tertentu.
Komponen yang mendukung siklus proses memberikan dukungan terbaik bagi coroutine untuk cakupan logis di aplikasi Anda. Dokumen ini menjelaskan cara menggunakan coroutine secara efektif dengan komponen yang mendukung siklus proses.
Menambahkan dependensi
Cakupan coroutine bawaan yang dijelaskan dalam topik ini dimuat dalam Lifecycle API. Pastikan untuk menambahkan dependensi yang sesuai saat menggunakan cakupan ini.
- Untuk utilitas ViewModel di Compose, gunakan
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version"). - Untuk utilitas Lifecycle di Compose, gunakan
implementation("androidx.lifecycle:lifecycle-runtime-compose:$lifecycle_version").
Cakupan coroutine berbasis Lifecycle
Compose dan library Lifecycle menyediakan cakupan bawaan berikut yang dapat Anda gunakan di aplikasi.
ViewModelScope
A ViewModelScope ditentukan untuk setiap ViewModel di aplikasi Anda. Setiap
coroutine yang diluncurkan dalam cakupan ini akan otomatis dibatalkan jika ViewModel di
hapus. Coroutine sangat berguna di sini jika Anda memiliki pekerjaan yang harus dilakukan hanya saat ViewModel aktif. Misalnya, jika Anda menghitung beberapa data untuk tata letak, sebaiknya tentukan cakupan pekerjaan tersebut ke ViewModel agar saat ViewModel dihapus, pekerjaan otomatis dibatalkan untuk menghindari konsumsi resource.
Anda dapat mengakses CoroutineScope dari ViewModel melalui properti viewModelScope dari ViewModel, seperti yang ditunjukkan dalam contoh berikut:
class MyViewModel: ViewModel() {
init {
viewModelScope.launch {
// Coroutine that will be canceled when the ViewModel is cleared.
}
}
}
Untuk kasus penggunaan lanjutan lainnya, Anda dapat meneruskan CoroutineScope kustom langsung ke konstruktor ViewModel untuk mengganti viewModelScope default. Pendekatan ini menawarkan lebih banyak kontrol dan fleksibilitas, terutama untuk:
Pengujian: Memungkinkan Anda menyuntikkan
TestScope, sehingga lebih mudah mengontrol waktu dan memverifikasi perilaku coroutine dalam uji unit.Konfigurasi kustom: Anda dapat mengonfigurasi cakupan dengan
CoroutineDispatchertertentu (sepertiDispatchers.Defaultuntuk komputasi berat) atauCoroutineExceptionHandlerkustom sebelum ViewModel memulai pekerjaannya.
Cakupan terikat komposisi
Efek samping seperti animasi, panggilan jaringan, atau timer harus dicakup ke siklus proses composable. Dengan cara ini, saat composable keluar dari layar (keluar dari komposisi), coroutine yang berjalan akan otomatis dibatalkan untuk mencegah kebocoran memori.
Compose menyediakan LaunchedEffect API untuk menangani cakupan Komposisi
secara deklaratif.
LaunchedEffect membuat CoroutineScope yang memungkinkan Anda menjalankan fungsi penangguhan. Cakupan ini terikat ke siklus proses Komposisi composable, bukan Siklus Proses Aktivitas host.
- Masuk: Coroutine dimulai saat composable memasuki komposisi.
- Keluar: Coroutine dibatalkan saat composable keluar dari komposisi.
- Diluncurkan kembali: Jika ada kunci yang diteruskan ke
LaunchedEffectberubah, coroutine yang ada akan dibatalkan dan coroutine baru akan diluncurkan.
Contoh berikut menunjukkan cara menggunakan LaunchedEffect untuk membuat animasi berdenyut. Coroutine terikat ke keberadaan composable dalam komposisi dan bereaksi terhadap perubahan konfigurasi:
// 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) } }
Untuk mengetahui informasi selengkapnya tentang LaunchedEffect, lihat Efek samping di Compose.
Pengumpulan alur berbasis Siklus proses
Untuk mengumpulkan alur dengan aman di Jetpack Compose, gunakan API
collectAsStateWithLifecycle. Fungsi tunggal ini mengonversi Flow menjadi objek State Compose dan otomatis mengelola langganan siklus proses untuk Anda. Secara default, pengumpulan dimulai saat siklus proses STARTED dan berhenti saat siklus proses STOPPED. Untuk mengganti perilaku default ini, teruskan parameter minActiveState dengan metode siklus proses yang Anda inginkan, seperti Lifecycle.State.RESUMED.
Contoh berikut menunjukkan cara mengumpulkan StateFlow ViewModel dalam composable:
@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) /* ... */ }
Pengumpulan paralel beberapa alur
Di Compose, Anda dapat mengumpulkan beberapa alur secara paralel dengan mendeklarasikan beberapa variabel status. Karena collectAsStateWithLifecycle mengelola cakupan dasarnya sendiri, pengumpulan paralel ditangani secara otomatis:
@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()
// ...
}
Menghitung nilai secara asinkron menggunakan Alur
Jika Anda perlu menghitung nilai secara asinkron, gunakan StateFlow dengan operator stateIn.
Cuplikan berikut menggunakan Flow standar yang dikonversi ke StateFlow. Parameter
WhileSubscribed(5000) membuat langganan tetap aktif selama lima
detik setelah UI menghilang untuk menangani perubahan konfigurasi.
val uiState: StateFlow<Result> = flow {
emit(repository.fetchData())
}
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = Result.Loading
)
Gunakan collectAsStateWithLifecycle untuk mengonversi nilai yang dikumpulkan menjadi Compose
State, sehingga UI Anda dapat bereaksi secara reaktif setiap kali data berubah.
Untuk mengetahui informasi selengkapnya tentang status, lihat Status dan Jetpack Compose.
Referensi lainnya
Konten tampilan
Contoh
Direkomendasikan untuk Anda
- Catatan: teks link ditampilkan saat JavaScript nonaktif
- Menangani Siklus Proses dengan Komponen Berbasis Siklus Proses
- Memuat dan menampilkan data yang dibagi-bagi