Android开发 了解ViewModel
前言
ViewModel是google推出的一个数据处理框架,ViewModel类是被设计用来以可感知生命周期的方式存储和管理 UI 相关数据ViewModel中数据会一直存活即使 activity configuration发生变化.另外它生来可能目的就是与Fragment在数据共享上进行配合的.
使用它常与LiveData数据前台类(类似观察者模式的数据实体回调类)进行配合以前使用,如果你未了解LiveData建议你先了解它Android开发 LiveData与MutableLiveData详解 然后在回头在来看这篇博客
在总结下有的这些特征:
1.让数据与UI隔离:让ViewModel来获取数据加工数据并且回调给UI层.明确职责工作分离(参考MVP,MVVM这些框架结构)
2.数据与生命周期绑定:ViewModel与注册的Activity的生命周期绑定,有着与Activity同步的生命周期,如下图.这样就算网络请求的数据的异步回来后Activity已经销毁也不会出现问题,因为ViewModel也会被销毁终止数据的回调.

3.数据持久化:ViewModel不会因为屏幕的旋转导致Activity重新创建而重置数据.(这样避免了Activity被旋转数据丢失的问题)
4.与其他Activity独立:ViewModel的数据是独立的,它跟每一个绑定的Activity都是实例一个单独的数据(意思是它无法跟多个Activity绑定后同步共享数据)
5.天生为了配合Fragment:ViewModel可以与一个Activity与多个Fragment绑定后共享数据.(你终于可以不用很蛋疼的把Fragment的数据暂存到Activity里了)并且可以都与他们的生命周期关联.这样Fragment短暂的生命周期将不在让你烦恼数据的暂存问题.
依赖
implementation "androidx.fragment:fragment:1.1.0"
implementation "androidx.lifecycle:lifecycle-viewmodel:2.1.0"
implementation "androidx.lifecycle:lifecycle-extensions:2.1.0"
androidx.lifecycle:lifecycle-extensions:2.1.0 是ViewModelProviders的实现依赖,如果不导入就没有这个。
创建与绑定Activity
创建ViewModel
public class DemoViewModel extends ViewModel {
// TODO: Implement the ViewModel
@Override
protected void onCleared() {
super.onCleared();
//清除的方法,这个方法需要让你处理一些网络请求的停止或者数据加工的逻辑停止,它与绑定的Activity在销毁的时候触发.你不需要手动在Activity里调用它
}
}
绑定Activity
public class Demo1Activity extends AppCompatActivity {
private static final String TAG = "Demo1Activity";
private DemoViewModel mDemoViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo);
mDemoViewModel = ViewModelProviders.of(this).get(DemoViewModel.class);//获取ViewModel,让ViewModel与此activity绑定
}
}
以上简单继承和注册后就与Activity绑定了,它是单例模式的这点你可以在of()方法里看到它实现了单例(一个Activity只有一个单例),另外在Fragment的方式也是与Activity相同的方式如下:
mViewModel = ViewModelProviders.of(getActivity()).get(DemoViewModel.class);
这样你就将Activity和Fragment之间可以用ViewModel进行数据上的共享与同步了
简单的demo
实际使用的时候是与LiveData一起配合使用的,这里提供一个简单的demo了解下实际使用.
创建LiveData类
public class DemoData extends LiveData<DemoData> {
private int tag1;
private int tag2;
public int getTag1() {
return tag1;
}
public void setTag1(int tag1) {
this.tag1 = tag1;
postValue(this);
}
public int getTag2() {
return tag2;
}
public void setTag2(int tag2) {
this.tag2 = tag2;
postValue(this);
}
}
创建ViewModel并且在内部实例化LiveData
public class DemoViewModel extends ViewModel {
// TODO: Implement the ViewModel
private DemoData mDemoData = new DemoData();
public DemoData getDemoData() {
return mDemoData;
}
@Override
protected void onCleared() {
super.onCleared();
//清除的方法,这个方法需要让你处理一些网络请求的停止或者数据加工的逻辑停止
}
}
绑定Activity,模拟数据变化
public class Demo2Activity extends AppCompatActivity {
private static final String TAG = "Demo2Activity";
private Button mBtnAddData;
private DemoViewModel mDemoViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo2);
mBtnAddData = findViewById(R.id.btn_add_data);
mDemoViewModel = ViewModelProviders.of(this).get(DemoViewModel.class);//获取ViewModel,让ViewModel与此activity绑定
mDemoViewModel.getDemoData().observe(this, new Observer<DemoData>() { //注册观察者,观察数据的变化
@Override
public void onChanged(DemoData demoData) {
Log.e(TAG, "onChanged: 数据有更新");
}
});
mBtnAddData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e(TAG, "onClick: 已经点击");
mDemoViewModel.getDemoData().setTag1(123); //这里手动用按键点击更新数据
}
});
}
}
绑定Fragment
public class DemoFragment extends Fragment {
private static final String TAG = "DemoFragment";
private DemoViewModel mViewModel;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.demo1_fragment, container, false);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// TODO: Use the ViewModel
mViewModel = ViewModelProviders.of(getActivity()).get(DemoViewModel.class);
mViewModel.getDemoData().observe(this, new Observer<DemoData>() {
@Override
public void onChanged(DemoData demoData) {
Log.e(TAG, "onChanged: 数据有更新");
}
});
}
}
Fragment绑定ViewModel , of(getActivity())与of(this)的区别
mViewModel = ViewModelProviders.of(getActivity()).get(DemoViewModel.class); //使用getActivity()获得的ViewModel 作用域在Activity里和所有他创建碎片的里,意思是你在其他Fragment也获取相同内存地址的ViewModel mViewModel = ViewModelProviders.of(this).get(DemoViewModel.class); //这个ViewModel是独立的,只为这个Fragment单独服务,其他Fragment无法获取到相同内存地址的ViewModel
end
Android开发 了解ViewModel的更多相关文章
- android开发基础(ViewModel)
今天学习了ViewModel,其是Jetpack的一个类,它可以将界面中的数据独立出来,这样不会造成页面上信息的丢失. 我跟着视频做了一个简单的实例: 首先创建项目的时候它和以往的项目会有些不一样,因 ...
- Android开发总结
出来工作半年多了,没啥好交代的,就说说自己半年来的Android开发经历. 1.IDE 这半年来,从Eclipse到Android Studio,经历了两个IDE,在这里做一下简单的评价. ...
- Android开发利器之Data Binding Compiler V2 —— 搭建Android MVVM完全体的基础
原创声明: 该文章为原创文章,未经博主同意严禁转载. 前言: Android常用的架构有:MVC.MVP.MVVM,而MVVM是唯一一个官方提供支持组件的架构,我们可以通过Android lifecy ...
- Android 开发技术周报 Issue#277
新闻 Android 11界面再调整:加入快速截屏.多任务向国产ROM看齐 最新版Android 11推送 谷歌Pixel 5被曝光:支持反向充电 4月Android系统版本分布:8.0 Oreo最主
- 【Android开发高手笔记】Dagger2和它在SystemUI上的应用
和人类需要群居一样,程序界的进程.线程也需要通信往来.它们的交流则依赖模块之间.文件之间产生的关系.如何快速地搞清和构建这种关系,同时还能减轻彼此的依赖,需要开发者们认真思考. 我们将这种需求称之为依 ...
- 优秀Android开发简历都是这么写,你学会也可以进大厂
最近收了很多程序员的简历,工作经验从1年到十几年不等.发现一个问题,工作经验范围差不多的程序员,简历看起来也差不多... 为啥程序员的简历如此统一?正好最近看到一个分享也分析了这个问题,结合我个人的一 ...
- 我们是Android开发,我们都有着光明的未来
作为一名程序员经常会逛v2ex论坛,前几天逛着玩的时候忽然发现一篇文章,标题非常吸引眼球名字叫中年危机的终极解法,作为一个步入而立之年的老人,心里非常激动,到底是啥解决法呢,于是迅速点进去查看. 进去 ...
- 如何看待Android开发的“前景和内卷”
我们首先来意淫一波 5G时代Android即将崛起,Android将与物联网强强联合,配合上5G信息高速传递的模式,再搭配物联网号召的"万物互通"的旗号,同时各位Android开发 ...
- 大厂需要什么样的 Android 开发?
前言 昨天和一个百度的朋友闲聊,他说根据最近招聘 Android工程师的经验来看,大部分候选人在工作 3 年的时候基本都会遇上一道难过的坎. 为啥这么说呢? 因为工作一段时间之后,大部分工程师都已经完 ...
随机推荐
- Excel函数——ANSI字符集与Code、Char、Asc函数
小叙背景 Windows系统下,默认的字符集为ANSI,该字符编码方式在不同语言环境下采用不同的编码方案,在中文系统下ANSI编码是GBK.ANSI由ASCII扩展而来,ANSI下无论何种具体的编码方 ...
- redis 分析rdb中key
1.问题: 单位一个redis集群内存报警,想找出所有的key的列表? 2.解决办法: 网上搜索是可以用redis-rdb-tools 这个工具进行分析 (1)centos6 默认安装python2. ...
- windows 开启管理员权限
在使用cmd为windows系统的电脑添加一条路由的时候,发现提示我权限不足,经过我的查找,需要在 我的电脑 右键 管理 本地用户管理 打开用户一栏 找到管理员账户 右键打开属 ...
- ASP.NET MVC 解决账号重复登录问题
解决重复登录 用到了 .net 身份票证 和Global全局处理文件 第一步 登录方法 传入用户名 private void GetOnline(string Name) { Hashtable S ...
- 使用dd生成文件
使用dd命令快速生成大文件或者小文件的方法 转载自:http://blog.csdn.net/cywosp/article/details/9674757 在程序的测试中有些场景需要大 ...
- ps切图的基本操作
参考线和辅助线 ctrl+r呼出标尺,只有在移动工具(快捷键v)下,鼠标左键从标尺上可以拖出来新的参考线.将参考线拖回标尺即是删除. 导出切片 快捷键ctrl+alt+shift+s ,选择png-2 ...
- paper 16 : 计算机视觉领域博客资源
这是收录的图像视觉领域的博客资源的第一部分,包含:中国内地.香港.台湾 这些名人大家一般都熟悉,本文仅收录了包含较多资料的个人博客,并且有不少更新,还有些名人由于分享的paper.code或者数据集不 ...
- hive shell参数
Hive Shell参数 1.Hive命令行 语法结构 hive [-hiveconf x=y]* [<-i filename>]* [<-f filename>|<-e ...
- BZOJ 2159: Crash 的文明世界(组合数学+第二类斯特林数+树形dp)
传送门 解题思路 比较有意思的一道数学题.首先\(n*k^2\)的做法比较好想,就是维护一个\(x^i\)这种东西,然后转移的时候用二项式定理拆开转移.然后有一个比较有意思的结论就是把求\(x^i\) ...
- 「THUSC 2016」成绩单 & 方块消除 (区间dp)
成绩单 $f[l][r][mi][mx]$表示从l到r发到还没发的部分的最小值为mi最大值为mx时的最小代价. $f[l][r][0][0]$表示从l到r全部发完的代价. 自己写的无脑dp,枚举中转点 ...