واجهات برمجة التطبيقات ViewModel Scoping API جزء من Android Jetpack.

النطاق هو المفتاح لاستخدام نماذج ViewModels بفعالية. يتم تحديد نطاق كل نموذج عرض على كائن ينفّذ واجهة ViewModelStoreOwner. هناك العديد من واجهات برمجة التطبيقات التي تتيح لك إدارة نطاق ViewModels بسهولة أكبر. يوضح هذا المستند بعض الأساليب الرئيسية التي يجب أن تعرفها.

تتيح لك الطريقة ViewModelProvider.get() الحصول على مثيل من ViewModel على مستوى أي ViewModelStoreOwner. بالنسبة إلى مستخدمي لغة Kotlin، تتوفّر وظائف إضافة مختلفة لحالات الاستخدام الأكثر شيوعًا. تستخدم جميع عمليات تنفيذ دوال إضافة Kotlin واجهة برمجة التطبيقات ViewModelProvider تلقائيًا.

ViewModels التي تم تحديد نطاقها لأقرب ViewModelStoreOwner

يمكنك تحويل نموذج العرض إلى نشاط أو جزء أو وجهة في رسم بياني للتنقّل. تتيح لك وظائف الإضافة viewModels() التي توفّرها مكتبات "النشاط" و"أجزاء" و"التنقل" ودالة viewModel() في Compose الحصول على مثيل من ViewModel على مستوى أقرب ViewModelStoreOwner.

المشاهدات

import androidx.activity.viewModels

class MyActivity : AppCompatActivity() {
    // ViewModel API available in activity.activity-ktx
    // The ViewModel is scoped to `this` Activity
    val viewModel: MyViewModel by viewModels()
}

import androidx.fragment.app.viewModels

class MyFragment : Fragment() {
    // ViewModel API available in fragment.fragment-ktx
    // The ViewModel is scoped to `this` Fragment
    val viewModel: MyViewModel by viewModels()
}

المشاهدات

import androidx.lifecycle.ViewModelProvider;

public class MyActivity extends AppCompatActivity {
    // The ViewModel is scoped to `this` Activity
    MyViewModel viewModel = new ViewModelProvider(this).get(MyViewModel.class);
}

public class MyFragment extends Fragment {
    // The ViewModel is scoped to `this` Fragment
    MyViewModel viewModel = new ViewModelProvider(this).get(MyViewModel.class);
}

إنشاء

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, the host Fragment,
    // or the host Activity.
    viewModel: MyViewModel = viewModel()
) { /* ... */ }

عرض النماذج على نطاق أي ViewModelStoreOwner

تستخدم الدالتان ComponentActivity.viewModels() وFragment.viewModels() في نظام "العرض" والدالة viewModel() في "إنشاء" معلَمة ownerProducer اختيارية يمكنك استخدامها لتحديد ViewModelStoreOwner مثال نموذج العرض الذي يتم تحديد نطاقه له. يوضح النموذج التالي كيفية الحصول على مثيل لـ ViewModel على نطاق الجزء الرئيسي:

المشاهدات

import androidx.fragment.app.viewModels

class MyFragment : Fragment() {

    // ViewModel API available in fragment.fragment-ktx
    // The ViewModel is scoped to the parent of `this` Fragment
    val viewModel: SharedViewModel by viewModels(
        ownerProducer = { requireParentFragment() }
    )
}

المشاهدات

import androidx.lifecycle.ViewModelProvider;

public class MyFragment extends Fragment {

    SharedViewModel viewModel;

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        // The ViewModel is scoped to the parent of `this` Fragment
        viewModel = new ViewModelProvider(requireParentFragment())
            .get(SharedViewModel.class);
    }
}

إنشاء

import androidx.lifecycle.viewmodel.compose.viewModel

@Composable
fun MyScreen(
    context: Context = LocalContext.current,
    // ViewModel API available in lifecycle.lifecycle-viewmodel-compose
    // The ViewModel is scoped to the parent of the host Fragment
    // where this composable function is called
    viewModel: SharedViewModel = viewModel(
        viewModelStoreOwner = (context as Fragment).requireParentFragment()
    )
) { /* ... */ }

يعد الحصول على نموذج عرض على نطاق النشاط من جزء من حالات الاستخدام الشائعة. عند تنفيذ هذا الإجراء، استخدِم activityViewModels() دالة إضافة المشاهدات المتاحة. إذا كنت لا تستخدم طرق العرض وKotlin، يمكنك استخدام نفس واجهات برمجة التطبيقات كما سبق وأن تم تمرير المالك الصحيح.

المشاهدات

import androidx.fragment.app.activityViewModels

class MyFragment : Fragment() {

    // ViewModel API available in fragment.fragment-ktx
    // The ViewModel is scoped to the host Activity
    val viewModel: SharedViewModel by activityViewModels()
}

المشاهدات

import androidx.lifecycle.ViewModelProvider;

public class MyFragment extends Fragment {

    SharedViewModel viewModel;

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        // The ViewModel is scoped to the host Activity
        viewModel = new ViewModelProvider(requireActivity())
            .get(SharedViewModel.class);
    }
}

إنشاء

import androidx.lifecycle.viewmodel.compose.viewModel

@Composable
fun MyScreen(
    context: Context = LocalContext.current,
    // ViewModel API available in lifecycle.lifecycle-viewmodel-compose
    // The ViewModel is scoped to the Activity of the host Fragment
    // where this composable function is called
    viewModel: SharedViewModel = viewModel(
        viewModelStoreOwner = (context as Fragment).requireActivity()
    )
) { /* ... */ }

النماذج المعروضة في الرسم البياني للتنقل

الرسوم البيانية للتنقل هي أيضًا مالكي متاجر ViewModel. إذا كنت تستخدم جزء التنقل أو إنشاء التنقل، يمكنك الحصول على مثال لنموذج العرض على نطاق رسم بياني للتنقل باستخدام navGraphViewModels(graphId) وظيفة الإضافة "طرق العرض".

المشاهدات

import androidx.navigation.navGraphViewModels

class MyFragment : Fragment() {

    // ViewModel API available in navigation.navigation-fragment
    // The ViewModel is scoped to the `nav_graph` Navigation graph
    val viewModel: SharedViewModel by navGraphViewModels(R.id.nav_graph)

    // Equivalent navGraphViewModels code using the viewModels API
    val viewModel: SharedViewModel by viewModels(
        { findNavController().getBackStackEntry(R.id.nav_graph) }
    )
}

المشاهدات

import androidx.lifecycle.ViewModelProvider;

public class MyFragment extends Fragment {

    SharedViewModel viewModel;

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        NavController navController = NavHostFragment.findNavController(this);
        NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.my_graph);

        // The ViewModel is scoped to the `nav_graph` Navigation graph
        viewModel = new ViewModelProvider(backStackEntry).get(SharedViewModel.class);
    }
}

إنشاء

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) على النحو التالي.

المشاهدات

import androidx.hilt.navigation.fragment.hiltNavGraphViewModels

class MyFragment : Fragment() {

    // ViewModel API available in hilt.hilt-navigation-fragment
    // The ViewModel is scoped to the `nav_graph` Navigation graph
    // and is provided using the Hilt-generated ViewModel factory
    val viewModel: SharedViewModel by hiltNavGraphViewModels(R.id.nav_graph)
}

المشاهدات

import androidx.hilt.navigation.HiltViewModelFactory;
import androidx.lifecycle.ViewModelProvider;

public class MyFragment extends Fragment {

    SharedViewModel viewModel;

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        NavController navController = NavHostFragment.findNavController(this);
        NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.my_graph);

        // The ViewModel is scoped to the `nav_graph` Navigation graph
        // and is provided using the Hilt-generated ViewModel factory
        viewModel = new ViewModelProvider(
            backStackEntry,
            HiltViewModelFactory.create(getContext(), backStackEntry)
        ).get(SharedViewModel.class);
    }
}

إنشاء

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)
        // ...
    }
}