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 و دامنه، منابع اضافی زیر را ببینید:

اسناد

محتوا را مشاهده می‌کند