API Cakupan ViewModel Bagian dari Android Jetpack.
Cakupan adalah kunci untuk menggunakan ViewModel secara efektif. Setiap ViewModel dicakup ke
objek yang menerapkan antarmuka ViewModelStoreOwner. Ada beberapa
API yang memungkinkan Anda mengelola cakupan ViewModel dengan lebih mudah.
Dokumen ini menguraikan beberapa teknik utama yang harus Anda ketahui.
Metode ViewModelProvider.get() memungkinkan Anda mendapatkan instance ViewModel
yang dicakupkan ke ViewModelStoreOwner apa pun. Untuk pengguna Kotlin, terdapat berbagai fungsi ekstensi yang tersedia untuk kasus penggunaan paling umum. Semua
penerapan fungsi ekstensi Kotlin menggunakan ViewModelProvider API di balik layar.
ViewModel yang dicakupkan ke ViewModelStoreOwner terdekat
Anda dapat menentukan cakupan ViewModel ke composable, Activity, atau
tujuan grafik Navigation. Fungsi viewModel() di Compose memungkinkan Anda mendapatkan instance ViewModel yang dicakupkan ke ViewModelStoreOwner terdekat.
import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( modifier: Modifier = Modifier, // ViewModel API available in lifecycle.lifecycle-viewmodel-compose // The ViewModel is scoped to the closest ViewModelStoreOwner provided // via the LocalViewModelStoreOwner CompositionLocal. In order of proximity, // this could be the destination of a Navigation graph // or the host Activity. viewModel: MyViewModel = viewModel() ) { /* ... */ }
ViewModel yang dicakupkan ke ViewModelStoreOwner apa pun
Fungsi viewModel() mengambil parameter viewModelStoreOwner opsional yang dapat Anda gunakan untuk menentukan ViewModelStoreOwner mana yang dicakupkan ke instance ViewModel.
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.ViewModelStoreOwner @Composable fun MyScreen( // A custom owner passed in, such as a parent NavBackStackEntry customOwner: ViewModelStoreOwner, // The ViewModel is now scoped to the provided customOwner viewModel: MyViewModel = viewModel(viewModelStoreOwner = customOwner) ) { /* ... */ }
ViewModel yang dicakupkan ke composable
Anda dapat menggunakan rememberViewModelStoreOwner() untuk mencakup ViewModel langsung ke situs panggilan composable. Hal ini sangat berguna untuk komponen UI yang ditambahkan atau dihapus secara dinamis dari layar berdasarkan status, seperti item halaman atau daftar lambat. Saat composable yang memiliki
ViewModelStoreOwner meninggalkan komposisi, ViewModelStore
terkait akan dihapus dan ViewModel akan dihancurkan.
Gunakan rememberViewModelStoreOwner() untuk membuat penyimpanan yang mendukung siklus proses dan dipertahankan meskipun konfigurasi diubah.
@Composable
fun RememberViewModelStoreOwnerSample() {
// Create a ViewModelStoreOwner scoped to this specific call site.
// When this composable leaves the composition,
// the associated ViewModelStore will be cleared.
val scopedOwner = rememberViewModelStoreOwner()
CompositionLocalProvider(LocalViewModelStoreOwner provides scopedOwner) {
// This ViewModel is scoped to `scopedOwner`.
// It will survive configuration changes but will be cleared when
// the composable is removed from the UI tree.
val viewModel = viewModel { TestViewModel("scoped_data") }
// Use the ViewModel
}
}
Untuk penerapan yang lebih kompleks, seperti HorizontalPager atau kasus yang memerlukan beberapa cakupan independen, gunakan rememberViewModelStoreProvider().
Hal ini memungkinkan Anda membuat instance ViewModelStoreOwner yang berbeda untuk kunci yang berbeda (seperti indeks halaman). Dengan cara ini, setiap halaman mempertahankan status ViewModel independennya sendiri.
@Composable
fun RememberViewModelStoreProviderSample() {
val storeProvider = rememberViewModelStoreProvider()
val pages = listOf("Page 1", "Page 2", "Page 3")
HorizontalPager(pageCount = pages.size) { page ->
// Create a ViewModelStoreOwner for the specific page using the provider.
val pageOwner = rememberViewModelStoreOwner(provider = storeProvider, key = page)
CompositionLocalProvider(LocalViewModelStoreOwner provides pageOwner) {
val pageViewModel = viewModel { TestViewModel(pages[page]) }
// Use pageViewModel
}
}
}
ViewModel yang dicakupkan ke grafik Navigation
Grafik Navigation juga merupakan pemilik penyimpanan ViewModel. Jika menggunakan
Navigation Compose, Anda bisa mendapatkan instance ViewModel yang dicakupkan ke grafik Navigation dengan fungsi
getBackStackEntry().
viewModel() mengambil instance dari ViewModelStoreOwner
yang disediakan oleh LocalViewModelStoreOwner CompositionLocal. Dalam aplikasi Compose umum yang menggunakan Jetpack Navigation, pemilik ini adalah entri back stack Navigation saat ini. Artinya, ViewModel tetap berada dalam memori selama tujuan tersebut ada di back stack.
import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyAppNavHost() { // ... composable("myScreen") { backStackEntry -> // Retrieve the NavBackStackEntry of "parentNavigationRoute" val parentEntry = remember(backStackEntry) { navController.getBackStackEntry("parentNavigationRoute") } // Get the ViewModel scoped to the `parentNavigationRoute` Nav graph val parentViewModel: SharedViewModel = viewModel(parentEntry) // ... } }
Jika menggunakan Hilt sebagai tambahan Jetpack Navigation, Anda dapat menggunakan
hiltNavGraphViewModels(graphId)
API sebagai berikut.
import androidx.hilt.navigation.compose.hiltViewModel @Composable fun MyAppNavHost() { // ... composable("myScreen") { backStackEntry -> val parentEntry = remember(backStackEntry) { navController.getBackStackEntry("parentNavigationRoute") } // ViewModel API available in hilt.hilt-navigation-compose // The ViewModel is scoped to the `parentNavigationRoute` Navigation graph // and is provided using the Hilt-generated ViewModel factory val parentViewModel: SharedViewModel = hiltViewModel(parentEntry) // ... } }
Referensi lainnya
Untuk mempelajari ViewModel dan cakupan lebih lanjut, lihat referensi tambahan berikut: