ViewModel को स्कोप करने वाले एपीआई Android Jetpack का हिस्सा हैं.
ViewModel का बेहतर तरीके से इस्तेमाल करने के लिए, स्कोप तय करना ज़रूरी है. हर ViewModel,
ऑब्जेक्ट के स्कोप में होता है जो ViewModelStoreOwner इंटरफ़ेस लागू करता है. ऐसे कई एपीआई हैं जिनकी मदद से, अपने ViewModels के स्कोप को ज़्यादा आसानी से मैनेज किया जा सकता है.
इस दस्तावेज़ में, कुछ अहम तकनीकों के बारे में बताया गया है.
ViewModelProvider.get() तरीके से, किसी भी ViewModelStoreOwner के स्कोप में मौजूद ViewModel का इंस्टेंस पाया जा सकता है. Kotlin का इस्तेमाल करने वाले लोगों के लिए, सबसे आम इस्तेमाल के मामलों के लिए अलग-अलग एक्सटेंशन फ़ंक्शन उपलब्ध हैं. Kotlin के सभी एक्सटेंशन फ़ंक्शन के लागू करने के तरीके, बैकग्राउंड में ViewModelProvider API का इस्तेमाल करते हैं.
ViewModels को सबसे नज़दीकी ViewModelStoreOwner के स्कोप में रखना
किसी ViewModel को कंपोज़ेबल, ऐक्टिविटी या
नेविगेशन ग्राफ़ के डेस्टिनेशन के स्कोप में रखा जा सकता है. Compose में मौजूद viewModel() फ़ंक्शन की मदद से, सबसे नज़दीकी ViewModelStoreOwner के स्कोप में मौजूद ViewModel का इंस्टेंस पाया जा सकता है.
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 को किसी कंपोज़ेबल के स्कोप में रखना
किसी ViewModel को सीधे तौर पर कंपोज़ेबल की कॉल साइट के स्कोप में रखने के लिए, rememberViewModelStoreOwner() का इस्तेमाल किया जा सकता है. यह खास तौर पर उन यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट के लिए काम का है जिन्हें स्क्रीन पर, स्थिति के आधार पर डाइनैमिक तरीके से जोड़ा या हटाया जाता है. जैसे, किसी पेज या लेज़ी लिस्ट के आइटम. जब कंपोज़ेबल, जिसका मालिक
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 से मिला है. Jetpack Navigation का इस्तेमाल करने वाले किसी सामान्य Compose ऐप्लिकेशन में, यह मालिक मौजूदा नेविगेशन बैक स्टैक एंट्री होती है. इसका मतलब है कि जब तक वह डेस्टिनेशन बैक स्टैक में मौजूद है, तब तक 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)
एपीआई का इस्तेमाल इस तरह किया जा सकता है.
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 और स्कोप के बारे में ज़्यादा जानने के लिए, यहां दिए गए अन्य संसाधन देखें: