前言

  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的更多相关文章

  1. android开发基础(ViewModel)

    今天学习了ViewModel,其是Jetpack的一个类,它可以将界面中的数据独立出来,这样不会造成页面上信息的丢失. 我跟着视频做了一个简单的实例: 首先创建项目的时候它和以往的项目会有些不一样,因 ...

  2. Android开发总结

    出来工作半年多了,没啥好交代的,就说说自己半年来的Android开发经历. 1.IDE      这半年来,从Eclipse到Android Studio,经历了两个IDE,在这里做一下简单的评价. ...

  3. Android开发利器之Data Binding Compiler V2 —— 搭建Android MVVM完全体的基础

    原创声明: 该文章为原创文章,未经博主同意严禁转载. 前言: Android常用的架构有:MVC.MVP.MVVM,而MVVM是唯一一个官方提供支持组件的架构,我们可以通过Android lifecy ...

  4. Android 开发技术周报 Issue#277

    新闻 Android 11界面再调整:加入快速截屏.多任务向国产ROM看齐 最新版Android 11推送 谷歌Pixel 5被曝光:支持反向充电 4月Android系统版本分布:8.0 Oreo最主

  5. 【Android开发高手笔记】Dagger2和它在SystemUI上的应用

    和人类需要群居一样,程序界的进程.线程也需要通信往来.它们的交流则依赖模块之间.文件之间产生的关系.如何快速地搞清和构建这种关系,同时还能减轻彼此的依赖,需要开发者们认真思考. 我们将这种需求称之为依 ...

  6. 优秀Android开发简历都是这么写,你学会也可以进大厂

    最近收了很多程序员的简历,工作经验从1年到十几年不等.发现一个问题,工作经验范围差不多的程序员,简历看起来也差不多... 为啥程序员的简历如此统一?正好最近看到一个分享也分析了这个问题,结合我个人的一 ...

  7. 我们是Android开发,我们都有着光明的未来

    作为一名程序员经常会逛v2ex论坛,前几天逛着玩的时候忽然发现一篇文章,标题非常吸引眼球名字叫中年危机的终极解法,作为一个步入而立之年的老人,心里非常激动,到底是啥解决法呢,于是迅速点进去查看. 进去 ...

  8. 如何看待Android开发的“前景和内卷”

    我们首先来意淫一波 5G时代Android即将崛起,Android将与物联网强强联合,配合上5G信息高速传递的模式,再搭配物联网号召的"万物互通"的旗号,同时各位Android开发 ...

  9. 大厂需要什么样的 Android 开发?

    前言 昨天和一个百度的朋友闲聊,他说根据最近招聘 Android工程师的经验来看,大部分候选人在工作 3 年的时候基本都会遇上一道难过的坎. 为啥这么说呢? 因为工作一段时间之后,大部分工程师都已经完 ...

随机推荐

  1. CUDA编程入门笔记

    1.线程块(block)是独立执行的,在执行的过程中线程块之间互不干扰,因此它们的执行顺序是随机的 2.同一线程块中的线程可以通过访问共享内存(shared memory)或者通过同步函数__sync ...

  2. C# WinfForm 控件之dev报表 XtraReport (五) 并排报表

    有了前边的基础这个就很简单了,建一个容器报表 在detail,上放两个xrsubReport.再做两个明细报表,分别指定到xrsubreport就可以了

  3. hdu6321 /// 状压DP

    题目大意: 将一个 顶点不重复的边 的边集称为图中的matching 在一个n个点的零图中进行m次操作 + u v为在u v之间加一条边 存在重边 - u v为去掉u v之间的一条边 每次操作后 输出 ...

  4. 大型站点图片server架构的演进

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/dinglang_2009/article/details/31450731 在主流的Web站点中,图 ...

  5. Dubbo多注册中心和Zookeeper服务的迁移

    一.Dubbo多注册中心 1. 应用场景 例如阿里有些服务来不及在青岛部署,只在杭州部署,而青岛的其它应用需要引用此服务,就可以将服务同时注册到两个注册中心. consumer.xml <?xm ...

  6. 什么是URI、URL、URN、URC和Data URI?

    前言 不知道大家有没有电话拨号通过'猫'上网的经历,那时测试网络是否连接,最好的方式就是打开浏览器输入: www.baidu.com 那会管这一连串字母叫' 网址 '.之后上大学(计算机专业),知道了 ...

  7. .Net平台调用の初识

    前言 工作过程中难免遇到混合编程,现在我们要谈的是C#和c++语言的编程.C#要调用C++的库目前可选主要有两种方式:Com技术和平台调用(P/Invoke).现在我们要谈的是P/Invoke技术. ...

  8. 类 __init__的注意事项

    class Dog():  class类 后面的ClassName类名第一个字母一定要大写. def __init__(self,name,age):    注意init前后是英文格式下,前后都是两道 ...

  9. fedora 28 missing PROG bison

    yum install bison Missing PROG dlltool Missing PROG flex Missing PROG mt

  10. SLF4J log4j 不打印日志

      SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no ...