واجهات برمجة التطبيقات لتحديد نطاق ViewModel جزء من Android Jetpack.
يُعدّ النطاق أساسيًا لاستخدام ViewModels بفعالية. يتم تحديد نطاق كل ViewModel لكائن يطبّق واجهة ViewModelStoreOwner. تتوفّر عدة واجهات برمجة تطبيقات تتيح لك إدارة نطاق ViewModels بسهولة أكبر.
توضّح هذه المستندات بعضًا من التقنيات الرئيسية التي يجب معرفتها.
تتيح لك طريقة ViewModelProvider.get() الحصول على مثيل من ViewModel محدّد نطاقه لأي ViewModelStoreOwner. بالنسبة إلى مستخدمي Kotlin، تتوفّر دوال إضافية مختلفة لحالات الاستخدام الأكثر شيوعًا. تستخدم جميع عمليات تنفيذ الدوال الإضافية في Kotlin واجهة برمجة التطبيقات ViewModelProvider تحت الغطاء.
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 يمكنك استخدامها لتحديد ViewModelStoreOwner الذي يتم تحديد نطاق مثيل 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) ) { /* ... */ }
ViewModels محدّدة نطاقها لعنصر قابل للإنشاء
يمكنك استخدام rememberViewModelStoreOwner() لتحديد نطاق ViewModel مباشرةً لموقع طلب عنصر قابل للإنشاء. ويكون ذلك مفيدًا بشكل خاص لمكوّنات واجهة المستخدم التي تتم إضافتها أو إزالتها ديناميكيًا من الشاشة استنادًا إلى الحالة، مثل عناصر صفحة أو قائمة مؤجّلة. عندما يغادر العنصر القابل للإنشاء الذي يملك الـ
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 محدّدة نطاقها لرسم بياني للتنقّل
تُعدّ الرسومات البيانية للتنقّل أيضًا مالكة لمتجر ViewModel. إذا كنت تستخدم
Navigation Compose، يمكنك الحصول على مثيل من
ViewModel محدّد نطاقه لرسم بياني للتنقّل باستخدام الدالة
getBackStackEntry().
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) // ... } }
إذا كنت تستخدم Hilt بالإضافة إلى Jetpack Navigation، يمكنك استخدام الـ
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 والنطاق، يُرجى الاطّلاع على المراجع الإضافية التالية: