ViewModel Scoping APIs بخشی از Android Jetpack.
محدوده کلید استفاده مؤثر از ViewModels است. هر ViewModel به شیئی محدود میشود که میانای ViewModelStoreOwner را پیادهسازی میکند. چندین میانای برنامهسازی کاربردی وجود دارد که به شما امکان میدهد دامنه ViewModels خود را راحتتر مدیریت کنید.
این سند برخیاز تکنیکهای کلیدی را که باید بدانید شرح میدهد.
روش ViewModelProvider.get() به شما امکان میدهد نمونهای از ViewModel را که به هر ViewModelStoreOwner محدود شده است دریافت کنید. برای کاربران Kotlin، توابع افزونه متفاوتی برای رایجترین موارد استفاده دردسترس است. همه پیادهسازیهای تابع افزونه Kotlin از ViewModelProvider API در پشت صحنه استفاده میکنند.
ViewModels با دامنه نزدیکترین ViewModelStoreOwner
میتوانید ViewModel را به ترکیبپذیر، «فعالیت»، یا مقصد «نمودار پیمایش» محدود کنید. تابع
viewModel() در Compose به شما امکان میدهد نمونهای از ViewModel را
در محدوده نزدیکترین ViewModelStoreOwner دریافت کنید.
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() ) { /* ... */ }
ViewModels با دامنه ViewModelStoreOwner
تابع viewModel() یک پارامتر اختیاری viewModelStoreOwner میگیرد که میتوانید از آن برای مشخص کردن اینکه نمونه ViewModel به کدام ViewModelStoreOwner محدود میشود استفاده کنید.
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) ) { /* ... */ }
ViewModels scoped to a composable
میتوانید از rememberViewModelStoreOwner() برای محدود کردن ViewModel مستقیماً به
محل فراخوانی composable استفاده کنید. این امر بهویژه برای مؤلفههای میانای کاربری که
براساس وضعیت بهطور پویا به صفحه اضافه یا از آن برداشته میشوند، مانند
موارد یک صفحه یا فهرست تنبل، مفید است. وقتی composable که مالک
ViewModelStoreOwner است ترکیببندی را ترک میکند، ViewModelStore مربوطه
پاک میشود و ViewModel ازبین میرود.
از rememberViewModelStoreOwner() برای ایجاد فروشگاه آگاه از چرخه حیات استفاده کنید که
دربرابر تغییرات پیکربندی دوام میآورد.
@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
}
}
برای پیادهسازیهای پیچیدهتر، مانند HorizontalPager یا مواردی که به چندین گستره مستقل نیاز دارند، از rememberViewModelStoreProvider() استفاده کنید.
این کار به شما امکان میدهد نمونههای ViewModelStoreOwner متمایزی برای کلیدهای مختلف (مانند نمایههای صفحه) تولید کنید. بهاینترتیب، هر صفحه وضعیت ViewModel مستقل خودش را حفظ میکند.
@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
}
}
}
ViewModels scoped to the Navigation graph
نمودارهای پیمایش همچنین مالکان فروشگاه ViewModel هستند. اگر از
Navigation Compose استفاده میکنید، میتوانید با تابع
getBackStackEntry()، نمونهای از
ViewModel را که به نمودار Navigation محدود شده است دریافت کنید.
viewModel() نمونه را از نزدیکترین ViewModelStoreOwner
ارائهشده توسط LocalViewModelStoreOwner CompositionLocal بازیابی میکند. در یک برنامه معمولی Compose که از Jetpack Navigation استفاده میکند، این مالک ورودی فعلی پشته قبلیها در Navigation است. این یعنی ViewModel تا زمانی که آن مقصد در پشته قبلیها وجود داشته باشد در حافظه باقی میماند.
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) // ... } }
اگر علاوهبر Jetpack Navigation از Hilt استفاده میکنید، میتوانید از
hiltNavGraphViewModels(graphId)
API بهصورت زیر استفاده کنید.
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) // ... } }
منابع بیشتر
برای کسب اطلاعات بیشتر درباره ViewModels و دامنه، منابع اضافی زیر را ببینید: