ממשקי API להגדרת היקף ב-ViewModel חלק מ-Android Jetpack.

היקף הוא המפתח לשימוש יעיל ב-ViewModels. כל ViewModel הוא בהיקף של שמטמיע את הממשק ViewModelStoreOwner. יש מספר ממשקי API שמאפשרים לכם לנהל בקלות רבה יותר את היקף ה-ViewModels. במסמך הזה מפורטות כמה מהטכניקות העיקריות שכדאי להכיר.

השיטה ViewModelProvider.get() מאפשרת לקבל מופע של ViewModel בהיקף לכל ViewModelStoreOwner. למשתמשי Kotlin: והפונקציות של התוספים שזמינים בתרחישי השימוש הנפוצים ביותר. כל הקוטלין הטמעות של פונקציות תוספים משתמשות ב-ViewModelProvider API באופן כללי.

ViewModels מהיקף ה-ViewModelStoreOwner הקרוב ביותר

ניתן להגדיר ל-ViewModel את ההיקף של פעילות, מקטע או יעד של תרשים ניווט. תוסף viewModels() הפונקציות שמספקות ספריות 'פעילות', 'מקטעים' ו'ניווט', הפונקציה viewModel() בכתיבה מאפשרת לך לקבל מופע של 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. הדוגמה הבאה מראה איך לקבל מופע של 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()
    )
) { /* ... */ }

קבלת ViewModel ברמת הפעילות מ-Fragment היא תרחיש לדוגמה נפוץ. מתי כדי לעשות את זה, צריך להשתמש בactivityViewModels() הפונקציה של תוסף הצפיות זמינה. אם אתם לא משתמשים ב-Views וב-Kotlin אפשר להשתמש באותם ממשקי API שמפורטים למעלה, ועל ידי העברת הבעלים הנכונים.

צפיות

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. אם אתם משתמשים מקטע ניווט או כתיבת ניווט, אפשר לקבל מופע של 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, אפשר להשתמש hiltNavGraphViewModels(graphId) API באופן הבא.

צפיות

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