ViewModel 作用域 API 属于 Android Jetpack 的一部分。
作用域是有效使用 ViewModel 的关键。每个 ViewModel 的作用域都与实现 ViewModelStoreOwner
接口的对象相关联。有一些 API 允许您更轻松地管理 ViewModel 的作用域。本文档概述了一些您应该了解的关键技术。
ViewModelProvider.get()
方法允许您获取作用域为任何 ViewModelStoreOwner
的 ViewModel 实例。对于 Kotlin 用户,针对最常见用例,有不同的扩展函数可用。所有 Kotlin 扩展函数的实现都在幕后使用 ViewModelProvider API。
作用域为最接近的 ViewModelStoreOwner 的 ViewModel
您可以将 ViewModel 绑定到 Activity、Fragment 或 Navigation 图的目的地。由 Activity、Fragment 和 Navigation 库提供的 viewModels()
扩展函数,以及 Compose 中的 viewModel()
函数允许您获取绑定到最近的 ViewModelStoreOwner
的 ViewModel 实例。
视图
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); }
Compose
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 的 ViewModel
View 系统中的 ComponentActivity.viewModels()
和 Fragment.viewModels()
函数,以及 Compose 中的 viewModel()
函数接受一个可选的 ownerProducer
参数,您可以使用它来指定将 ViewModel 实例绑定到哪个 ViewModelStoreOwner
。以下示例显示了如何获取绑定到父级 Fragment 的 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); } }
Compose
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() ) ) { /* ... */ }
从 Fragment 获取 Activity 级别的 ViewModel 是一个常见的用例。在这种情况下,可以使用 activityViewModels()
视图扩展函数。如果您没有使用视图和 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); } }
Compose
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() ) ) { /* ... */ }
绑定到 Navigation 图的 ViewModel
Navigation 图也是 ViewModel 存储拥有者。如果您使用的是 Navigation Fragment 或 Navigation Compose,您可以使用 navGraphViewModels(graphId)
视图扩展函数获取绑定到 Navigation 图的 ViewModel 实例。
视图
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); } }
Compose
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.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); } }
Compose
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) // ... } }
为您推荐
- 注意:当 JavaScript 关闭时,链接文本将显示
- 布局和绑定表达式
- ViewModel 概述