当前位置: 首页 > news >正文

Android ViewModel

一问:ViewModel如何保证应用配置变化后能够自动继续存在,其原理是什么,ViewModel的生命周期和谁绑定的?

ViewModel 的确能够在应用配置发生变化(例如屏幕旋转)后继续存在,这得益于 Android 系统的 ViewModelProvider 和其依赖的 ViewModelStoreOwner。 它并不是直接与 Activity 或 Fragment 的生命周期绑定,而是与 ViewModelStore 绑定。

原理:

  1. ViewModelStore: 这是 ViewModel 的存储库。它持有一个 ViewModel 的集合,并负责创建和销毁 ViewModel 实例。 关键在于,ViewModelStore 的生命周期与 Activity 或 Fragment 的生命周期 不同。 当 Activity 或 Fragment 销毁时,ViewModelStore 并不立即被销毁,而是保留在 ViewModelStoreOwner 中。

  2. ViewModelStoreOwner: 这是一个接口,Activity 和 Fragment 都实现了这个接口。它提供对 ViewModelStore 的访问。 ViewModelProvider 通过 ViewModelStoreOwner 获取 ViewModelStore 来管理 ViewModel。

  3. ViewModelProvider: 这个类是获取 ViewModel 的入口。它会首先检查 ViewModelStore 中是否存在对应的 ViewModel 实例。如果存在,则直接返回已存在的实例;如果不存在,则创建一个新的 ViewModel 实例并将其添加到 ViewModelStore 中。

  4. 配置变化: 当配置发生变化(例如屏幕旋转)时,Activity 或 Fragment 会被销毁并重建。但是,由于 ViewModelStore 保持着 ViewModel 实例,ViewModelProvider 会从 ViewModelStore 中获取已存在的 ViewModel 实例,而不是重新创建新的实例。这保证了数据的持久性。

  5. ViewModel 的销毁: ViewModel 只有在其关联的 ViewModelStore 被销毁时才会被销毁。这通常发生在 Activity 或 Fragment 彻底销毁并从 ViewModelStoreOwner 中移除时。

ViewModel 生命周期和绑定:

ViewModel 的生命周期不直接与 Activity 或 Fragment 的生命周期绑定,而是与 ViewModelStore 绑定。更准确地说,ViewModel 的生命周期绑定到 ViewModelStoreOwner 的生命周期。当 ViewModelStoreOwner (例如 Activity 或 Fragment) 被销毁并且从 ViewModelStoreOwner 中移除时,与之关联的 ViewModelStore 才会被清除,这时 ViewModel 才会被销毁。 只要 ViewModelStore(宿主Application) 存在,ViewModel 就存在。和OnPause/OnResume/

总结:

ViewModel 通过 ViewModelStore 和 ViewModelStoreOwner 机制,实现了在配置变化后数据能够保持的效果。它巧妙地利用了 ViewModelStore 的独立生命周期,将 ViewModel 的生命周期与 Activity 或 Fragment 的生命周期解耦,从而避免了配置变化导致数据丢失的问题。 这使得开发人员可以专注于业务逻辑,而无需担心配置更改带来的数据管理问题。

二 问:Activity如何实现ViewModelStoreOwner 接口?

Activity 实现 ViewModelStoreOwner 接口的方式很简单,它直接返回一个内部维护的 ViewModelStore 实例。 没有复杂的实现逻辑,主要就是持有并提供这个 ViewModelStore

以下是 Activity 如何实现 ViewModelStoreOwner 的核心思想,以及代码片段的示意(实际实现可能因 Android 版本而略有差异,但核心概念不变):

  1. 内部成员变量: Activity 会持有 ViewModelStore 的一个实例,通常是一个私有成员变量,例如 private ViewModelStore mViewModelStore;。 这个 ViewModelStore 实例在 Activity 的生命周期内被管理。

  2. getViewModelStore() 方法: Activity 实现 ViewModelStoreOwner 接口的唯一方法 getViewModelStore(),这个方法直接返回这个内部维护的 mViewModelStore 实例。 当 ViewModelProvider 需要访问 ViewModelStore 时,它会调用这个方法。

  3. 生命周期管理: 关键在于 Activity 如何在适当的生命周期方法中创建和销毁 mViewModelStore。 通常,mViewModelStore 会在 onCreate() 中创建,并在 onDestroy() 中销毁。 这确保了 ViewModelStore 的生命周期与 Activity 的生命周期紧密关联,但又略微延迟销毁。

代码示意 (简化):

public class MyActivity extends AppCompatActivity implements ViewModelStoreOwner {private ViewModelStore mViewModelStore;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// ... other initialization ...mViewModelStore = new ViewModelStore(); // 创建 ViewModelStore}@Overrideprotected void onDestroy() {super.onDestroy();if (mViewModelStore != null) {mViewModelStore.clear(); // 清空ViewModelStoremViewModelStore = null; // 避免内存泄漏}}@Overridepublic ViewModelStore getViewModelStore() {return mViewModelStore;}
}

这段代码只是一个简化的示意,实际的 Android Activity 实现可能更加复杂,可能包含一些额外的错误处理和生命周期检查,但是核心逻辑如上所述。 Android 系统内部会负责 ViewModelStore 的创建和管理,Activity 只需要提供一个接口来获取它。 通过这种方式,ViewModel 就可以与 Activity 的生命周期关联起来,并在配置变化时得到保留。

需要注意的是,虽然 ViewModelStore 在 onDestroy() 中被清除,但这并不是立即销毁 ViewModel 的时机。 ViewModel 会在 ViewModelStore 被完全释放后才会被销毁,这与 Activity 或 Fragment 的销毁时机略有延迟。 这种延迟确保了在 onDestroy() 之后,ViewModel 仍然有时间执行必要的清理工作。

三问:flow更新时如何变更以下NewsUiState类中的部分状态,而不是全部重新初始化

ViewModel() { val uiState: StateFlow<NewsUiState> = … }

如果 NewsUiState 是一个不可变的数据类,每次更新 StateFlow 都需要创建一个新的 NewsUiState 实例,这确实会增加初始化工作量,特别是当 NewsUiState 包含大量数据时。 仅仅修改部分状态就重新创建整个对象效率低下。

有几种更好的方法来处理这种情况,避免不必要的对象创建,并提高效率:

1. 使用 copy() 方法:

这是最简单和最常用的方法。 如果你的 NewsUiState 是一个数据类 (data class),它会自动生成一个 copy()


http://www.mrgr.cn/news/50034.html

相关文章:

  • 全金属的两足机器人钢铁侠开发
  • 闯关leetcode——100. Same Tree
  • 2024 年主流 10 大 CRM 系统盘点
  • 33条必看问题!腾讯云认证考试须知!
  • Jmeter 获取用户数据-全部登录
  • 电脑上怎么录制高清流畅视频?录制游戏的时候很卡怎么办?
  • 从“制造”到“智造”:中图光学测量仪器的进阶与应用
  • postgresql进行几何抽稀(DP抽稀)
  • 进程地址空间
  • 自动化检查网页的TDK,python+selenium自动化测试web的网页源代码中的title,Description,Keywords
  • 电子行业技术网站
  • 【2022统考真题】计算时间复杂度
  • Spring集成Redisson及存取几种基本类型数据
  • 已解决:“发生生成错误,是否继续并运行上次的成功的生成?”无法启动程序,系统找不到指定的文件
  • 代码随想录算法训练营Day07 | 454.四数相加II、383. 赎金信 、15. 三数之和 、18. 四数之和
  • ppt在线生成工具有哪些?6个好用的做ppt软件盘点!
  • crossover怎么运行exe文件,crossover如何安装Windows软件?crossover安装的软件无法打开怎么办
  • 从0到1打造我们专属的推荐系统
  • 推挽电路(图腾柱)
  • LeetCode Hot100 | Day4 | 层序遍历有序数组转搜索树验证搜索树搜索树中第K小的元素