Jetpack之ViewModel讲解
【1】关于ViewModel
ViewModel是Jetpack AAC的重要组件,同时也有一个同名抽象类。 ViewModel,意为 视图模型,即为界面准备数据的模型。简单理解就是,ViewModel为UI层提供数据。
- 官方文档定义如下:
- ViewModel 以注重生命周期的方式存储和管理界面相关的数据。(作用)
- ViewModel类让数据可在发生屏幕旋转等配置更改后继续留存。(特点)
到这里,你可能还是不清楚ViewModel到底是干啥的,别急,往下看。
①背景引出:
在详细介绍ViewModel前,先来看下背景和问题点。
Activity可能会在某些场景(例如屏幕旋转)销毁和重新创建界面,那么存储在其中的界面相关数据都会丢失。例如,界面含用户信息列表,因配置更改而重新创建Activity 后,新 Activity必须重新请求用户列表,这会造成资源的浪费。能否直接恢复之前的数据呢?对于简单的数据,Activity 可以使用onSaveInstanceState() 方法保存 然后从 onCreate()中的Bundle恢复数据,但此方法仅适合可以序列化再反序列化的少量数据(IPC对Bundle有1M的限制),而不适合数量可能较大的数据,如用户信息列表或位图。那么如何做到 因配置更改而新建Activity后的数据恢复呢?
UI层(如 Activity 和 Fragment)经常需要通过逻辑层(如MVP中的Presenter)进行异步请求,可能需要一些时间才能返回结果,如果逻辑层持有UI层应用(如context),那么UI层需要管理这些请求,确保界面销毁后清理这些调用以避免潜在的内存泄露,但此项管理需要大量的维护工作。 那么如何更好的避免因异步请求带来的内存泄漏呢?
- 这时候ViewModel就闪亮出场了——ViewModel用于代替MVP中的Presenter,为UI层准备数据,用于解决上面两个问题。
②特点
1. 生命周期长于Activity
这是官方给的图。
看到在因屏幕旋转而重新创建Activity后,ViewModel对象依然会保留。 只有Activity真正Finish的时ViewModel才会被清除。
也就是说,因系统配置变更Activity销毁重建,ViewModel对象会保留并关联到新的Activity。而Activity的正常销毁(系统不会重建Activity)时,ViewModel对象是会清除的。
那么很自然的,因系统配置变更Activity销毁重建,ViewModel内部存储的数据 就可供重新创建的Activity实例使用了。这就解决了第一个问题。
- 同样都是生命周期中的onDestroy为什么上一个没有没有销毁ViewModel而下一个却销毁了呢?
当Activity 处于前台的时候被销毁了,那么得到的 ViewModel 是之前实例过的 ViewModel;如果 Activity
处于后台时被销毁了,那么得到的 ViewModel 不是同一个。举例说,如果 Activity因为配置发生变化而被重建了,那么当重建的时候,ViewModel是之前的实例;如果因为长期处于后台而被销毁了,那么重建的时候,ViewModel就不是之前的实例了。而上一个onDestroy是前台的销毁,而后一个是后台的onDestroy
2. 不持有UI层引用
我们知道,在MVP的Presenter中需要持有IView接口来回调结果给界面。
而ViewModel是不需要持有UI层引用的,那结果怎么给到UI层呢?答案就是使用上一篇中介绍的基于观察者模式的LiveData。 并且,ViewModel也不能持有UI层引用,因为ViewModel的生命周期更长。
所以,ViewModel不需要也不能 持有UI层引用,那么就避免了可能的内存泄漏,同时实现了解耦。这就解决了第二个问题。
【2】如何使用:
①思路:
- 导入依赖
- 继承ViewModel自定义MyViewModel
- 在MyViewModel中编写获取UI数据的逻辑
- 使用LiveData将获取到的UI数据抛出
- 在Activity/Fragment中使用ViewModelProvider获取MyViewModel实例
- 观察MyViewModel中的LiveData数据,进行对应的UI更新。
举个例子,如果您需要在Activity中显示用户信息,那么需要将获取用户信息的操作分放到ViewModel中,代码如下:
public class UserViewModel extends ViewModel {private MutableLiveData<String> userLiveData ;private MutableLiveData<Boolean> loadingLiveData;public UserViewModel() {userLiveData = new MutableLiveData<>();loadingLiveData = new MutableLiveData<>();}//获取用户信息,假装网络请求 2s后 返回用户信息public void getUserInfo() {loadingLiveData.setValue(true);new AsyncTask<Void, Void, String>() {@Overrideprotected void onPostExecute(String s) {loadingLiveData.setValue(false);userLiveData.setValue(s);//抛出用户信息}@Overrideprotected String doInBackground(Void... voids) {try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}String userName = "AAAAAABBBBBBBBBBBBCCCCCCCCC";return userName;}}.execute();}public LiveData<String> getUserLiveData() {return userLiveData;}public LiveData<Boolean> getLoadingLiveData() {return loadingLiveData;}
}
UserViewModel继承ViewModel,然后逻辑很简单:假装网络请求 2s后 返回用户信息,其中userLiveData用于抛出用户信息,loadingLiveData用于控制进度条显示。
再看UI层:
public class UserActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);...Log.i(TAG, "onCreate: ");TextView tvUserName = findViewById(R.id.textView);ProgressBar pbLoading = findViewById(R.id.pb_loading);//获取ViewModel实例ViewModelProvider viewModelProvider = new ViewModelProvider(this);UserViewModel userViewModel = viewModelProvider.get(UserViewModel.class);//观察 用户信息userViewModel.getUserLiveData().observe(this, new Observer<String>() {@Overridepublic void onChanged(String s) {// update ui.tvUserName.setText(s);}});userViewModel.getLoadingLiveData().observe(this, new Observer<Boolean>() {@Overridepublic void onChanged(Boolean aBoolean) {pbLoading.setVisibility(aBoolean?View.VISIBLE:View.GONE);}});//点击按钮获取用户信息findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {userViewModel.getUserInfo();}});}@Overrideprotected void onStop() {super.onStop();Log.i(TAG, "onStop: ");}@Overrideprotected void onDestroy() {super.onDestroy();Log.i(TAG, "onDestroy: ");}
}
页面有个按钮用于点击获取用户信息,有个TextView展示用户信息。 在onCreate()中先 创建ViewModelProvider实例,传入的参数是ViewModelStoreOwner,Activity和Fragment都是其实现。然后通过ViewModelProvider的get方法 获取ViewModel实例,然后就是 观察ViewModel中的LiveData。
②总结:
ViewModel的使用很简单,作用和原来的Presenter一致。只是要结合LiveData,UI层观察即可。
ViewModel的创建必须通过ViewModelProvider。
注意到ViewModel中没有持有任何UI相关的引用。
旋转手机重建Activity后,数据确实恢复了。
参考:鸿祥_AAC_ViewModel
Jetpack之ViewModel讲解相关推荐
- Android Jetpack组件ViewModel基本使用和原理分析
本文整体流程:首先要知道什么是 ViewModel,然后演示一个例子,来看看 ViewModel 是怎么使用的,接着提出问题为什么是这样的,最后读源码来解释原因! 1.什么是ViewModel 1.1 ...
- Lifecycle、LiveData、ViewModel讲解之Lifecycle
Lifecycle.LiveData.ViewModel介绍 在 Android 框架中定义的大多数应用组件都存在生命周期.生命周期由操作系统或进程中运行的框架代码管理.它们是 Android 运作方 ...
- Android Jetpack 之 ViewModel
前言 在 Android 中,ViewModel 的作用就是在 UI 控制器( 如 Activity.Fragment)的生命周期中保存和管理 UI 相关的数据.ViewModel 保存的数据在配置更 ...
- jetpack之ViewModel
ViewModel类旨在以注重生命周期的方式存储和管理界面相关的数据.ViewModel类让数据可在发生屏幕旋转等配置更改后继续留存. 摘自官方文档 Android 框架可以管理界面控制器(如 Act ...
- Android Jetpack之DataBinding+ViewModel+LiveData+Room
Android Jetpack之ViewModel.LiveData Android Jetpack之LifeCycle 前言 Jetpack是一个由多个技术库组成的套件,可帮助开发者遵循最佳做法,减 ...
- android jetpack ViewModel 报错解决方法
android jetpack 的viewmodel 部分,在activity里面写以下这行代码时会报错的解决方法: myViewModel = new ViewModelProvider(this ...
- ViewModel优雅的弹加载窗和获取Context
前言 目前安卓开发一般都是用的mvvm模式,Jetpack的ViewModel是必不可少的一部分,而vm的生命周期要比Activity和Fragment长的,所以其一般不推荐其直接持有A或F,因为可能 ...
- android mvvm框架搭建_轻松搭建基于JetPack组件的MVVM框架
原文链接:轻松搭建基于JetPack组件的MVVM框架 - 掘金 Brick github gitee 介绍 辅助android开发者搭建基于JetPack组件构建MVVM框架的注解处理框架.通过注解 ...
- 架构演进|研究mvp到mvvm(传统架构mvvm和Jetpack下的区别)
mvp.mvvm架构演进|研究 MVP架构实现 定义数据结构类型 MVP架构改进--反射获取泛型类型实例 MVVM架构基础 配置DataBinding 添加Jetpack组件 MVVM架构下的项目层次 ...
最新文章
- web开发性能优化---用户体验篇
- java中BigDecimal的常见用法
- c语言总是说有一个错误,我的电脑上的c语言为何老有一个错误
- Java基础面试16问
- 见识可能比聪明更重要!
- 中信银行MySQL面试_【深圳中信银行信用卡中心面试】面试题_面试经验_面试流程-看准网...
- 以太坊Dapp项目-网页钱包开发手册
- oracle set autocommit,Oracle Sqlplus SET AUTOCOMMIT
- Oracle学习笔记:oracle的启动过程
- 每天10个Linux命令三
- requests第三方库在测试中的使用
- 搭建属于自己的复古传奇私服
- 全国大学生智能汽车竞赛山东省赛区获奖队伍信息
- 单龙芯3A3000-7A1000PMON研究学习-(1)硬件原理图
- 1553B 协议详解
- 请你讲讲分布式系统中的限流器一般如何实现?
- 嵌入式设计与开发项目-ADC键盘扫描程序设计
- socket读写返回值的处理
- 连接大智慧数据库接口
- 小豹子带你看源码:Java 线程池(三)提交任务