Android MVVM之ViewModel的详解与使用 |
您所在的位置:网站首页 › mvvmlight框架 › Android MVVM之ViewModel的详解与使用 |
一、介绍
ViewModel 类是一种业务逻辑或屏幕级状态容器。它用于将状态公开给界面,以及封装相关的业务逻辑。 它的主要优点是,它可以缓存状态,并可在配置更改后持久保留相应状态。这意味着在 activity 之间导航时或进行配置更改后(例如旋转屏幕时),界面将无需重新提取数据。 ViewModel 的优势 ViewModel 的替代方案是保存要在界面中显示的数据的普通类。在 activity 或 Navigation 目的地之间导航时,这可能会造成问题。此时,如果您不利用保存实例状态机制存储相应数据,系统便会销毁相应数据。ViewModel 提供了一个便捷的数据持久性 API,可以解决此问题。 ViewModel 类的主要优势实际上有两个方面: 它允许您持久保留界面状态。 它可以提供对业务逻辑的访问权限。 持久性ViewModel 允许数据在 ViewModel 持有的状态和 ViewModel 触发的操作结束后继续存在。这种缓存意味着在常见的配置更改(例如屏幕旋转)完成后,您无需重新提取数据。 作用域实例化 ViewModel 时,您会向其传递实现 ViewModelStoreOwner 接口的对象。它可能是 Navigation 目的地、Navigation 图表、activity、fragment 或实现接口的任何其他类型。然后,ViewModel 的作用域将限定为 ViewModelStoreOwner 的 Lifecycle。它会一直保留在内存中,直到其 ViewModelStoreOwner 永久消失。 有一系列类是 ViewModelStoreOwner 接口的直接或间接子类。直接子类为 ComponentActivity、Fragment 和 NavBackStackEntry。 当 ViewModel 的作用域 fragment 或 activity 被销毁时,异步工作会在作用域限定到该 fragment 或 activity 的 ViewModel 中继续进行。这是持久性的关键。 实现 ViewModelviewModel是一个类,我们在使用的时候,只要继承就可以了,但是viewModel和UI数据更新是通过LiveData,这就是所谓的MVVM的核心所在。 class DiceRollViewModel : ViewModel() { private var data: MutableLiveData?=null fun getData(): MutableLiveData { if (data == null) { data = MutableLiveData() } return data!! } fun updateValue(){ val value=kotlin.random.Random.nextInt(1,100); data?.value="随机生成数为${value}" } } viewModel的创建使用viewModel的核心是想通过viewModel来管理生命周期,所以创建的时候不是通过直接new出来,而是有专门的工具ViewModelProvider ViewModelProvider:使用两种构造如下: public constructor(owner: ViewModelStoreOwner) public constructor(owner: ViewModelStoreOwner, factory: Factory)因为fragment和Activity内部已处理了ViewModelStoreOwner,所以可以借助ViewModelProvider直接使用 正常使用: viewModel = ViewModelProvider(this).get(DiceRollViewModel::class.java)如果需要factory创建,可以使用factory from的方法 companion object { @JvmStatic fun from(vararg initializers: ViewModelInitializer): Factory = InitializerViewModelFactory(*initializers) } 小试牛刀: class TestViewModelActivity : BaseActivity() { private lateinit var bind: MyVideModelBind private lateinit var viewModel: DiceRollViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) bind = DataBindingUtil.setContentView(this, R.layout.layout_viewmodel_demo) viewModel = ViewModelProvider(this).get(DiceRollViewModel::class.java) viewModel.getData().observe(this, Observer { bind.value = it }) bind.btnUpdate.setOnClickListener { viewModel.updateValue() } } }![]() ViewModel通常不应引用视图、Lifecycle 或可能存储对 activity 上下文的引用的任何类。由于 ViewModel 的生命周期大于界面的生命周期,因此在 ViewModel 中保留与生命周期相关的 API 可能会导致内存泄漏。 ViewModel 的生命周期按照依赖项注入的最佳实践,ViewModel 可以在其构造函数中将依赖项作为参数。这大多是网域层或数据层中的类型。由于框架提供 ViewModel,因此需要一种特殊机制来创建 ViewModel 的实例。该机制是 ViewModelProvider.Factory 接口。只有此接口的实现才能在适当的作用域内实例化 ViewModel。 包含 CreationExtras 的 ViewModel如果 ViewModel 类在其构造函数中接收依赖项,请提供用于实现 ViewModelProvider.Factory 接口的工厂。替换 create(Class, CreationExtras) 函数以提供 ViewModel 的新实例 借助 CreationExtras,您可以访问有助于实例化 ViewModel 的相关信息。下面列出了可以通过 extra 访问的键: 键 功能 ViewModelProvider.NewInstanceFactory.VIEW_MODEL_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 作用域 API作用域是有效使用 ViewModel 的关键。每个 ViewModel 的作用域都限定为一个实现 ViewModelStoreOwner 接口的对象。有多个 API 可帮助您更轻松地管理 ViewModel 的作用域。本文档简要介绍了您应该了解的一些关键技术 ViewModel 的作用域限定为最近的 ViewModelStoreOwner可以指定哪个fragment或者Activity的主题 val viewModel: MyiewModel by viewModels( ownerProducer = { requireParentFragment() }) ViewModel 的作用域限定为 Navigation关于Navigation怎么使用,可以看我的一篇文章: Android 导航之Navigation 组件的介绍与使用Navigation 图也是 ViewModel Store Owner。如果您使用的是 Navigation Fragment 或 Navigation Compose,可以使用 navGraphViewModels(graphId) val viewModel: MyViewModel by viewModels( { findNavController().getBackStackEntry(R.id.nav_graph) } ) 源码分析:在绑定完Navigation,其内部已支持存储,ViewModelStore private final HashMap mViewModelStores = new HashMap(); 以及状态保存saveStateHandleNavigation的生命周期,同样可以同步宿主的生命周期。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |