前言

  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. 设计模式四人帮(GOF)是什么?

    1994年,有四位作者:Erich Gamma,Richard Helm,Ralph Johnson和John Vlissides发表了一本题为<设计模式 - 可重用的面向对象软件元素>的 ...

  2. Laravel/php 一些调试技巧

    1. 模型属性不知道哪里修改? 直接覆盖模型的 setAttribute 方法,监测到某一个属性改动的时候,抛一个异常就可以看到堆栈了 use Illuminate\Database\Eloquent ...

  3. 52-Ubuntu-打包压缩-2-打包/解包

    tar是Linux中最常用的备份工具,此命令可以把一系列文件打包到一个大文件中,也可以把一个打包的大文件恢复成一系列文件. 序号 命令 作用 01 tar -cvf 打包文件.tar 被打包文件 打包 ...

  4. hdu 6437 /// 最小费用最大流 负花费 SPFA模板

    题目大意: 给定n,m,K,W 表示n个小时 m场电影(分为类型A.B) K个人 若某个人连续看了两场相同类型的电影则失去W 电影时间不能重叠 接下来给定m场电影的 s t w op 表示电影的 开始 ...

  5. json传参报错

    restful接口报错: com.fasterxml.jackson.core.JsonParseException: Unexpected character ('e' (code 101)): w ...

  6. kernel32 的 GetVersionExA/W

    今天接到一个问题,说Kernel32 模块的 GetVersionEx 获取系统版本不准确, 然后让我查查什么原因, 我当时就想,它不准,就用ntdll的 RtlGetVersion 阿,或者 Rtl ...

  7. 【转】谈一谈 Normalize.css

    原文链接: https://www.jianshu.com/p/9d7ff89757fd 笔记: 如何使用?

  8. map方法的简单使用

    假设有一个数组a,将a中的数值以2倍的形式放到b数组中 <!DOCTYPE html> <html lang="en"> <head> < ...

  9. Bribing FIPA

    Bribing FIPA 给出多棵有n个节点的有根树,第i个节点有一个权值\(a_i\),定义一个点能控制的点为其所有的子节点和它自己,询问选出若干个点的最少的权值之和,并且能够控制大于等于m个点,\ ...

  10. SOLID设计原则

    SOLID设计原则 Single Responsibility Principle单一职责原则 单一职责原则(SRP)表明一个类有且只有一个职责. 一个类就像容器一样,它能添加任意数量的属性.方法等. ...