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 berbasis siklus proses memberikan dukungan kelas satu untuk coroutine untuk cakupan logis di aplikasi Anda. Dokumen ini menjelaskan cara menggunakan coroutine secara efektif dengan komponen berbasis siklus proses.
Menambahkan dependensi
Cakupan coroutine bawaan yang dijelaskan dalam topik ini terdapat 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
ViewModelScope ditentukan untuk setiap ViewModel di aplikasi Anda. Setiap coroutine yang diluncurkan dalam cakupan ini akan otomatis dibatalkan jika ViewModel dihapus. Coroutine berguna di sini saat Anda memiliki pekerjaan yang perlu dilakukan
hanya jika 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 menggantikan viewModelScope default. Pendekatan ini menawarkan kontrol dan fleksibilitas yang lebih besar, terutama untuk:
Pengujian: Memungkinkan Anda memasukkan
TestScope, sehingga memudahkan kontrol waktu dan verifikasi perilaku coroutine dalam pengujian unit.Konfigurasi kustom: Anda dapat mengonfigurasi cakupan dengan
CoroutineDispatchertertentu (sepertiDispatchers.Defaultuntuk komputasi berat) atauCoroutineExceptionHandlerkustom bahkan 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 API LaunchedEffect untuk menangani pencakupan Komposisi
secara deklaratif.
LaunchedEffect membuat CoroutineScope yang memungkinkan Anda menjalankan fungsi
penangguhan. Cakupan ini terkait dengan siklus proses Komposisi composable, bukan
Siklus proses Aktivitas host.
- Masuk: Coroutine dimulai saat composable memasuki komposisi.
- Keluar: Coroutine dibatalkan saat composable keluar dari komposisi.
- Luncurkan kembali: Jika 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 terkait dengan 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 flow 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 dalam status
STARTED dan berhenti saat siklus proses dalam status 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 flow 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 Flow
Jika Anda perlu menghitung nilai secara asinkron, gunakan StateFlow dengan operator stateIn.
Cuplikan berikut menggunakan Flow standar yang dikonversi menjadi 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 diupdate secara reaktif setiap kali data berubah.
Untuk mengetahui informasi selengkapnya tentang status, lihat Status dan Jetpack Compose.
Referensi lainnya
Konten penayangan
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