ViewModel 概览 Android Jetpack 的一部分。
ViewModel
类旨在以注重生命周期的方式存储和管理界面相关数据。ViewModel
类让数据可在发生屏幕旋转等配置更改后继续留存。
Android 框架可以管理界面控制器(如 activity 和 fragment)的生命周期。Android 框架可能会决定销毁或重新创建界面控制器,以响应完全不受您控制的某些用户操作或设备事件。
如果系统销毁或重新创建界面控制器,则存储在其中的任何瞬态界面相关数据都会丢失。例如,应用的某个 Activity 中可能包含用户列表。因配置更改而重新创建 activity 后,新 activity 必须重新提取用户列表。对于简单的数据,activity 可以使用 onSaveInstanceState()
方法从 onCreate()
中的捆绑包恢复其数据,但此方法仅适合可以序列化再反序列化的少量数据,而不适合数量可能较大的数据,如用户列表或位图。
另一个问题是,界面控制器经常需要进行可能需要一些时间才能返回的异步调用。界面控制器需要管理这些调用,并确保系统在其销毁后清理这些调用以避免潜在的内存泄漏。此项管理需要大量的维护工作,并且在为配置更改重新创建对象的情况下,会造成资源的浪费,因为对象可能需要重新发出已经发出过的调用。
诸如 activity 和 fragment 之类的界面控制器主要用于显示界面数据、对用户操作做出响应或处理操作系统通信(如权限请求)。如果要求界面控制器也负责从数据库或网络加载数据,那么会使类越发膨胀。为界面控制器分配过多的责任可能会导致单个类尝试自己处理应用的所有工作,而不是将工作委托给其他类。以这种方式为界面控制器分配过多的责任也会大大增加测试的难度。
从界面控制器逻辑中分离出视图数据所有权的做法更易行且更高效。
实现 ViewModel
架构组件为界面控制器提供了 ViewModel
辅助程序类,该类负责为界面准备数据。在配置更改期间会自动保留 ViewModel
对象,以便它们存储的数据立即可供下一个 activity 或 fragment 实例使用。例如,如果您需要在应用中显示用户列表,请确保将获取和保留该用户列表的责任分配给 ViewModel
,而不是 activity 或 fragment,如以下示例代码所示:
View
class MyViewModel : ViewModel() { private val users: MutableLiveData<List<User>> by lazy { MutableLiveData<List<User>>().also { loadUsers() } } fun getUsers(): LiveData<List<User>> { return users } private fun loadUsers() { // Do an asynchronous operation to fetch users. } }
View
public class MyViewModel extends ViewModel { private MutableLiveData<List<User>> users; public LiveData<List<User>> getUsers() { if (users == null) { users = new MutableLiveData<List<User>>(); loadUsers(); } return users; } private void loadUsers() { // Do an asynchronous operation to fetch users. } }
然后,您可以从 activity 访问该列表,如下所示:
View
class MyActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { // Create a ViewModel the first time the system calls an activity's onCreate() method. // Re-created activities receive the same MyViewModel instance created by the first activity. // Use the 'by viewModels()' Kotlin property delegate // from the activity-ktx artifact val model: MyViewModel by viewModels() model.getUsers().observe(this, Observer<List<User>>{ users -> // update UI }) } }
View
public class MyActivity extends AppCompatActivity { public void onCreate(Bundle savedInstanceState) { // Create a ViewModel the first time the system calls an activity's onCreate() method. // Re-created activities receive the same MyViewModel instance created by the first activity. MyViewModel model = new ViewModelProvider(this).get(MyViewModel.class); model.getUsers().observe(this, users -> { // update UI }); } }
如果重新创建了该 activity,它接收的 MyViewModel
实例与第一个 activity 创建的实例相同。当所有者 Activity 完成时,框架会调用 ViewModel
对象的 onCleared()
方法,以便它可以清理资源。
ViewModel
对象存在的时间比视图或 LifecycleOwners
的特定实例存在的时间更长。这还意味着,您可以更轻松地编写涵盖 ViewModel
的测试,因为它不了解视图和 Lifecycle
对象。ViewModel
对象可以包含 LifecycleObservers
,如 LiveData
对象。但是,ViewModel
对象绝不能观察对生命周期感知型可观察对象(如 LiveData
对象)的更改。如果 ViewModel
需要 Application
上下文(例如,为了查找系统服务),它可以扩展 AndroidViewModel
类并设置接收 Application
的构造函数,因为 Application
类会扩展 Context
。
创建具有依赖项的 ViewModel
按照依赖项注入的最佳实践,ViewModel 可以在其构造函数中将依赖项作为参数。这大多是网域层或数据层中的类型。由于框架提供 ViewModel,因此需要一种特殊机制来创建 ViewModel 的实例。该机制是 ViewModelProvider.Factory
接口。只有此接口的实现才能在适当的作用域内实例化 ViewModel。
如果 ViewModel 类在其构造函数中接收依赖项,请提供用于实现 ViewModelProvider.Factory
接口的工厂。替换 create(Class<T>, CreationExtras)
函数以提供 ViewModel 的新实例。
借助 CreationExtras
,您可以访问有助于实例化 ViewModel 的相关信息。下面列出了可以通过 extra 访问的键:
键 | 功能 |
---|---|
ViewModelProvider.NewInstanceFactory.VIEW_MODEL_KEY |
此 Key 提供对您传递给 ViewModelProvider.get() 的自定义键的访问权限。 |
ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY |
提供对 Application 类实例的访问权限。 |
SavedStateHandleSupport.DEFAULT_ARGS_KEY |
提供对您在构造 SavedStateHandle 时应使用的参数 bundle 的访问权限。 |
SavedStateHandleSupport.SAVED_STATE_REGISTRY_OWNER_KEY |
提供对用于构造 ViewModel 的 SavedStateRegistryOwner 的访问权限。 |
SavedStateHandleSupport.VIEW_MODEL_STORE_OWNER_KEY |
提供对用于构造 ViewModel 的 ViewModelStoreOwner 的访问权限。 |
如需创建 SavedStateHandle
的新实例,请使用 CreationExtras.createSavedStateHandle()
.createSavedStateHandle()) 函数并将其传递给 ViewModel。
以下示例说明了如何提供 ViewModel 的实例,该实例会将作用域限定为 Application
类的存储库和 SavedStateHandle
作为依赖项:
View
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion.APPLICATION_KEY import androidx.lifecycle.createSavedStateHandle import androidx.lifecycle.viewmodel.CreationExtras class MyViewModel( private val myRepository: MyRepository, private val savedStateHandle: SavedStateHandle ) : ViewModel() { // ViewModel logic // ... // Define ViewModel factory in a companion object companion object { val Factory: ViewModelProvider.Factory = object : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun <T : ViewModel> create( modelClass: Class<T>, extras: CreationExtras ): T { // Get the Application object from extras val application = checkNotNull(extras[APPLICATION_KEY]) // Create a SavedStateHandle for this ViewModel from extras val savedStateHandle = extras.createSavedStateHandle() return MyViewModel( (application as MyApplication).myRepository, savedStateHandle ) as T } } } }
View
import static androidx.lifecycle.SavedStateHandleSupport.createSavedStateHandle; import static androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY; import androidx.lifecycle.SavedStateHandle; import androidx.lifecycle.ViewModel; import androidx.lifecycle.viewmodel.ViewModelInitializer; public class MyViewModel extends ViewModel { public MyViewModel( MyRepository myRepository, SavedStateHandle savedStateHandle ) { /* Init ViewModel here */ } static final ViewModelInitializer<MyViewModel> initializer = new ViewModelInitializer<>( MyViewModel.class, creationExtras -> { MyApplication app = (MyApplication) creationExtras.get(APPLICATION_KEY); assert app != null; SavedStateHandle savedStateHandle = createSavedStateHandle(creationExtras); return new MyViewModel(app.getMyRepository(), savedStateHandle); } ); }
然后,您可以在检索 ViewModel 的实例时使用此工厂:
View
import androidx.activity.viewModels class MyActivity : AppCompatActivity() { private val viewModel: MyViewModel by viewModels { MyViewModel.Factory } // Rest of Activity code }
View
import androidx.appcompat.app.AppCompatActivity; import androidx.lifecycle.ViewModelProvider; public class MyActivity extends AppCompatActivity { MyViewModel myViewModel = new ViewModelProvider( this, ViewModelProvider.Factory.from(MyViewModel.initializer) ).get(MyViewModel.class); // Rest of Activity code }
Compose
import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( modifier: Modifier = Modifier, viewModel: MyViewModel = viewModel(factory = MyViewModel.Factory) ) { // ... }
或者,使用 ViewModel 工厂 DSL 借助更惯用的 Kotlin API 创建工厂:
View
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion.APPLICATION_KEY import androidx.lifecycle.createSavedStateHandle import androidx.lifecycle.viewmodel.initializer import androidx.lifecycle.viewmodel.viewModelFactory class MyViewModel( private val myRepository: MyRepository, private val savedStateHandle: SavedStateHandle ) : ViewModel() { // ViewModel logic // Define ViewModel factory in a companion object companion object { val Factory: ViewModelProvider.Factory = viewModelFactory { initializer { val savedStateHandle = createSavedStateHandle() val myRepository = (this[APPLICATION_KEY] as MyApplication).myRepository MyViewModel( myRepository = myRepository, savedStateHandle = savedStateHandle ) } } } }
2.5.0 之前的 ViewModel 版本的工厂
如果您使用的是 2.5.0 之前的 ViewModel 版本,则需要从扩展 ViewModelProvider.Factory
的一部分类提供工厂并实现 create(Class<T>)
函数。根据 ViewModel 所需的依赖项,需要从以下类扩展不同的类:
AndroidViewModelFactory
(如果需要Application
类)。AbstractSavedStateViewModelFactory
(如果需要将SavedStateHandle
作为依赖项进行传递)。
如果不需要 Application
或 SavedStateHandle
,则只需从 ViewModelProvider.Factory
进行扩展。
以下示例对 ViewModel 使用 AbstractSavedStateViewModelFactory
,ViewModel 会将存储库和 SavedStateHandle
类型作为依赖项:
View
class MyViewModel( private val myRepository: MyRepository, private val savedStateHandle: SavedStateHandle ) : ViewModel() { // ViewModel logic ... // Define ViewModel factory in a companion object companion object { fun provideFactory( myRepository: MyRepository, owner: SavedStateRegistryOwner, defaultArgs: Bundle? = null, ): AbstractSavedStateViewModelFactory = object : AbstractSavedStateViewModelFactory(owner, defaultArgs) { @Suppress("UNCHECKED_CAST") override fun <T : ViewModel> create( key: String, modelClass: Class<T>, handle: SavedStateHandle ): T { return MyViewModel(myRepository, handle) as T } } } }
View
import androidx.annotation.NonNull; import androidx.lifecycle.AbstractSavedStateViewModelFactory; import androidx.lifecycle.SavedStateHandle; import androidx.lifecycle.ViewModel; public class MyViewModel extends ViewModel { public MyViewModel( MyRepository myRepository, SavedStateHandle savedStateHandle ) { /* Init ViewModel here */ } } public class MyViewModelFactory extends AbstractSavedStateViewModelFactory { private final MyRepository myRepository; public MyViewModelFactory( MyRepository myRepository ) { this.myRepository = myRepository; } @SuppressWarnings("unchecked") @NonNull @Override protected <T extends ViewModel> T create( @NonNull String key, @NonNull Class<T> modelClass, @NonNull SavedStateHandle handle ) { return (T) new MyViewModel(myRepository, handle); } }
然后,您可以使用工厂检索 ViewModel:
View
import androidx.activity.viewModels class MyActivity : AppCompatActivity() { private val viewModel: MyViewModel by viewModels { MyViewModel.provideFactory((application as MyApplication).myRepository, this) } // Rest of Activity code }
View
public class MyActivity extends AppCompatActivity { MyViewModel myViewModel = new ViewModelProvider( this, new MyViewModelFactory(((MyApplication) getApplication()).getMyRepository()) ).get(MyViewModel.class); // Rest of Activity code }
Compose
import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( modifier: Modifier = Modifier, viewModel: MyViewModel = viewModel( factory = MyViewModel.provideFactory( (LocalContext.current.applicationContext as MyApplication).myRepository, owner = LocalSavedStateRegistryOwner.current ) ) ) { // ... }
ViewModel 的生命周期
ViewModel
对象的作用域限定为获取 ViewModel
时传递给 ViewModelProvider
的 ViewModelStoreOwner
的 Lifecycle
。ViewModel
将一直留在内存中,直到其作用域 ViewModelStoreOwner
永久消失:
- 对于 activity,是在 activity 完成时。
- 对于 fragment,是在 fragment 分离时。
- 对于 Navigation 条目,是在 Navigation 条目从返回堆栈中移除时。
这使得 ViewModels 成为了存储在配置更改后仍然存在的数据的绝佳解决方案。
图 1 说明了 activity 经历屏幕旋转而后结束时所处的各种生命周期状态。该图还在关联的 activity 生命周期的旁边显示了 ViewModel
的生命周期。此图表说明了 Activity 的各种状态。这些基本状态同样适用于 Fragment 的生命周期。
您通常在系统首次调用 Activity 对象的 onCreate()
方法时请求 ViewModel
。系统可能会在 activity 的整个生命周期内多次调用 onCreate()
,如在旋转设备屏幕时。ViewModel
存在的时间范围是从您首次请求 ViewModel
直到 activity 完成并销毁。
ViewModel API
借助 ViewModelProvider.get()
方法,您可以获取作用域限定为任何 ViewModelStoreOwner
的 ViewModel 实例。对于 Kotlin 用户,我们针对最常见的用例提供了不同的扩展函数。所有 Kotlin 扩展函数实现在后台都使用 ViewModelProvider API。
ViewModel 的作用域限定为最近的 ViewModelStoreOwner
您可以将 ViewModel 的作用域限定为 Navigation 图的 activity、fragment 或目的地。借助 Activity 库、Fragment 库和 Navigation 库提供的 viewModels()
扩展函数,以及 Compose 中的 viewModel()
函数,您可以获取作用域限定为最近的 ViewModelStoreOwner
的 ViewModel 实例。
View
class MyActivity : AppCompatActivity() { // ViewModel API available in activity.activity-ktx // The ViewModel is scoped to `this` Activity val viewModel: MyViewModel by viewModels() } class MyFragment : Fragment() { // ViewModel API available in fragment.fragment-ktx // The ViewModel is scoped to `this` Fragment val viewModel: MyViewModel by viewModels() }
View
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
@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. This could be the // host Activity or Fragment, or destination of the Navigation graph. viewModel: MyViewModel = viewModel() ) { /* ... */ }
ViewModel 的作用域限定为任何 ViewModelStoreOwner
View 系统中的 ComponentActivity.viewModels()
函数和 Fragment.viewModels()
函数以及 Compose 中的 viewModel()
函数接受可选的 ownerProducer
参数,可用于指定 ViewModel 实例的作用域限定为哪个 ViewModelStoreOwner
。以下示例展示了如何获取作用域限定为父 fragment 的 ViewModel 实例:
View
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() } ) }
View
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
@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()
View 扩展函数。如果您没有使用 View 和 Kotlin,可以使用与上文相同的 API 并传递正确的所有者。
View
class MyFragment : Fragment() { // ViewModel API available in fragment.fragment-ktx // The ViewModel is scoped to the host Activity val viewModel: SharedViewModel by activityViewModels() }
View
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
@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 的作用域限定为 Navigation 图
Navigation 图也是 ViewModel Store Owner。如果您使用的是 Navigation Fragment 或 Navigation Compose,可以使用 navGraphViewModels(graphId)
View 扩展函数获取作用域限定为某个 Navigation 图的 ViewModel 实例。
View
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) } ) }
View
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
@Composable fun MyAppNavHost() { // ... composable("myScreen") { backStackEntry -> val parentEntry = remember(backStackEntry) { navController.getBackStackEntry("parentNavigationRoute") } // The ViewModel is scoped to the `parentNavigationRoute` Navigation graph val parentViewModel: SharedViewModel = viewModel(parentEntry) // ... } }
如果除了 Jetpack Navigation 之外,您还使用 Hilt,则可以使用 hiltNavGraphViewModels(graphId)
API,如下所示。
View
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) }
View
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
@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) // ... } }
在 fragment 之间共享数据
Activity 中的两个或更多 Fragment 需要相互通信是一种很常见的现象。想象一下拆分视图 (list-detail
) Fragment 的常见情况,假设您有一个 Fragment,在该 Fragment 中,用户从列表中选择一项,还有另一个 Fragment,用于显示选定项的内容。这种情况不太容易处理,因为这两个 Fragment 都需要定义某种接口描述,并且所有者 Activity 必须将两者绑定在一起。此外,这两个 Fragment 都必须处理另一个 Fragment 尚未创建或不可见的情况。
可以使用 ViewModel
对象解决这一常见的难点。这两个 fragment 可以使用其 activity 作用域共享 ViewModel
来处理此类通信,如以下示例代码所示:
View
class SharedViewModel : ViewModel() { val selected = MutableLiveData- () fun select(item: Item) { selected.value = item } } class ListFragment : Fragment() { private lateinit var itemSelector: Selector // Use the 'by activityViewModels()' Kotlin property delegate // from the fragment-ktx artifact private val model: SharedViewModel by activityViewModels() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) itemSelector.setOnClickListener { item -> // Update the UI } } } class DetailFragment : Fragment() { // Use the 'by activityViewModels()' Kotlin property delegate // from the fragment-ktx artifact private val model: SharedViewModel by activityViewModels() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) model.selected.observe(viewLifecycleOwner, Observer
- { item -> // Update the UI }) } }
View
public class SharedViewModel extends ViewModel { private final MutableLiveData<Item> selected = new MutableLiveData<Item>(); public void select(Item item) { selected.setValue(item); } public LiveData- getSelected() { return selected; } } public class ListFragment extends Fragment { private SharedViewModel model; public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class); itemSelector.setOnClickListener(item -> { model.select(item); }); } } public class DetailFragment extends Fragment { public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); SharedViewModel model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class); model.getSelected().observe(getViewLifecycleOwner(), item -> { // Update the UI. }); } }
请注意,这两个 fragment 都会检索包含它们的 activity。这样,当这两个 Fragment 各自获取 ViewModelProvider
时,它们会收到相同的 SharedViewModel
实例(其范围限定为该 Activity)。
此方法具有以下优势:
- activity 不需要执行任何操作,也不需要对此通信有任何了解。
- 除了
SharedViewModel
约定之外,Fragment 不需要相互了解。如果其中一个 Fragment 消失,另一个 Fragment 将继续照常工作。 - 每个 fragment 都有自己的生命周期,而不受另一个 fragment 的生命周期的影响。如果一个 fragment 替换另一个 fragment,界面将继续工作而没有任何问题。
将加载器替换为 ViewModel
CursorLoader
等加载器类经常用于使应用界面中的数据与数据库保持同步。您可以将 ViewModel
与一些其他类一起使用来替换加载器。使用 ViewModel
可将界面控制器与数据加载操作分离,这意味着类之间的强引用更少。
在使用加载器的一种常见方法中,应用可能会使用 CursorLoader
观察数据库的内容。当数据库中的值发生更改时,加载器会自动触发数据的重新加载并更新界面:

ViewModel
与 Room 和 LiveData 一起使用可替换加载器。ViewModel
确保数据在设备配置更改后仍然存在。Room 在数据库发生更改时通知 LiveData
,LiveData 继而使用修订后的数据更新界面。

将协程与 ViewModel 一起使用
ViewModel
支持 Kotlin 协程。如需了解详情,请参阅将 Kotlin 协程与 Android 架构组件一起使用。
更多信息
随着数据变得越来越复杂,您可能会选择使用单独的类加载数据。ViewModel
的用途是封装界面控制器的数据,以使数据在配置更改后仍然存在。如需了解如何在配置更改后加载、保留和管理数据,请参阅保存界面状态。
Android 应用架构指南建议构建存储区类来处理这些功能。
其他资源
如需详细了解 ViewModel
类,请参阅以下资源。
示例
- Android 架构组件基本示例
- Sunflower,这是一款园艺应用,展示了使用 Android Jetpack 进行 Android 开发的最佳做法。
Codelab
- 带 View 的 Android Room (Java) (Kotlin)
- Android 生命周期感知型组件 Codelab
博客
- ViewModel:简单示例
- ViewModel:持久性、onSaveInstanceState()、恢复界面状态和加载器
- ViewModel 和 LiveData:模式 + 反模式
- Kotlin 揭秘:理解速记 Lambda 语法
- Kotlin 揭秘:范围函数
- Kotlin 揭秘:何时使用自定义访问器
- 使用架构组件加载生命周期感知数据