什么是 ViewModel

ViewModel 旨在以注重生命周期的方式存储和管理界面相关数据。ViewModel 让数据可在发生屏幕旋转等配置更改后继续留存。

上面一段话是截取自官方文档对 ViewModel 的定义。ViewModel 是管理、存储数据的,并且屏幕发生旋转等行为之后,数据依旧保留。

ViewModel 的生命周期

学习 ViewModel 也必须要了解它到底能存活多久?下图可知,ViewModel 会从 Activity 创建之初,直到这个 Activity 被销毁为止。

ViewModel 使用场景

使用过 Vue 框架的人肯定有 VueX(Pinia)——状态管理的使用经验,组件与组件之间可以层层往下传递数据,而有时候子组件往上传递数据也有些麻烦,倒不如使用状态管理,也就是说,把这些共用的数据放在一个“地方”,让所有组件都可以访问到的一个容器。

其实,ViewModel 也可以这样来理解。一定要清楚,一个 Activity 就是一个页面,页面与页面之间不可能通过 ViewModel 来共享数据,使用场景比如:日期选择器(Fragment)选择完之后,日期数据要返回到 Activity 页面上,这个时候就可以借助于 ViewModel 来做。ViewModel 相当于 Activity 与 Fragment 之间的通信桥梁。

创建 ViewModel 类

实现一个继承 ViewModel 的子类:TimePickerViewModel。里面只来存储日期选择器选择之后保存的日期数据,类型为 MutableLiveData,其泛型是 String。在获取这个 dateValue 之前,要做一个非空判断。设置日期数据必须要调用 MutableLiveData 提供的setValue,否则不起效果。

public class TimePickerViewModel extends ViewModel {
private MutableLiveData<String> dateValue; public LiveData<String> getDateValue() {
if (dateValue == null) {
dateValue = new MutableLiveData<>();
}
return dateValue;
} public void setDateValue(String dateValue) {
this.dateValue.setValue(dateValue);
}
}

UI 界面

<TextView
android:id="@+id/time_picker_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="未选择日期" /> <TextView
android:id="@+id/time_picker_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="选择日期" />

点击选择日期文本之后,触发点击事件,打开日期选择器。下面是点击文本之后,日期选择器的代码:

public class TimePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener {

  @NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
final Calendar c = Calendar.getInstance();
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH);
int day = c.get(Calendar.DAY_OF_MONTH);
return new DatePickerDialog(getActivity(), this, year, month + 1, day);
} @Override
public void onDateSet(DatePicker datePicker, int i, int i1, int i2) {
TimePickerViewModel vm = new ViewModelProvider(requireActivity()).get(TimePickerViewModel.class);
vm.setDateValue(i + "-" + i1 + "-" + i2);
}
}

当选择日期成功之后,触发onDateSet,该函数中调用 ViewModelProvider 以修改 TimePickerViewModel 的字段。ViewModelProvider 需要获取 Activity 的实例,可以通过requireActivity()或者getActivity()来获取。

MainActivity

MainActivity 实现 OnClickListener 接口,这样做的好处就是添加多个事件监听都不需要 new OnClickListener 接口,直接给 setOnClickListener() 函数提供 this:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

  @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.time_picker_btn).setOnClickListener(this);
} @Override
public void onClick(View view) {
// 1. 实例化 TimePickerFragment
TimePickerFragment timePicker = new TimePickerFragment();
// 2. 显示日期选择器
timePicker.show(getSupportFragmentManager(), "datePicker");
// 3. 获取 TextView,展示的数据放在这里
TextView textview = findViewById(R.id.time_picker_text);
// 4. 观察 ViewModel 数据变化以更新 UI
TimePickerViewModel timePickerVM = new ViewModelProvider(this).get(TimePickerViewModel.class);
// 5. 观察数据变化
timePickerVM.getDateValue().observe(this, e -> {
// 6. 数据变化,把新的日期展示到 TextView 中
textview.setText(timePickerVM.getDateValue().getValue());
});
}
}
  1. 实例化 TimePickerFragment,构造日期选择器;
  2. 获取 TimePickerViewModel 对象,并观察数据是否发生变化;
  3. 如果数据发生变化,就把最新的日期显示到 TextView 上。

GitHub 仓库地址:Chap02-ViewModel

Android:ViewModel的更多相关文章

  1. Android:让WebView支持<input type=”file”…>元素

    最近在做一个活动页面:用户上传一张图片进行缩放.旋转后点击下一步填写内容后生成图片! 做好后经过各种测试是没有问题的,基本没有什么明显BUG,流程都能走通,但是嵌入到APP后,问题就来了! 在IOS上 ...

  2. android:ToolBar详解

    android:ToolBar详解(手把手教程) 泡在网上的日子 发表于 2014-11-18 12:49 第 124857 次阅读 ToolBar 42 来源 http://blog.mosil.b ...

  3. Android:学习AIDL,这一篇文章就够了(下)

    前言 上一篇博文介绍了关于AIDL是什么,为什么我们需要AIDL,AIDL的语法以及如何使用AIDL等方面的知识,这一篇博文将顺着上一篇的思路往下走,接着介绍关于AIDL的一些更加深入的知识.强烈建议 ...

  4. cocos2d-x for android:SimpleGame分析

    cocos2d-x for android:SimpleGame分析 作为cocos2d-x的标配DEMO,SimpleGame可算是给入门学cocos2d-x的俺们这些新手门学习的对象了,那么来分析 ...

  5. Android:布局实例之模仿微信Tab

    微信Tab预览效果: 思路: 1.用TabHost+RadioGroup搭建基本布局,以RadioGroup代替TabWidget 2.设置按钮和文字的的样式和selector 3.创建相应的Acti ...

  6. Android:什么是Holo?【Translated By KillerLegend】

    Android:什么是Holo? Martin Brinkmann on May 6, 2013 in Google Android 3 [Translated By KillerLegend] 当你 ...

  7. Android:AlertDialog对话框

    1.简单的ALertDialog: Dialog alertDialog = new AlertDialog.Builder(this) .setTitle("标题") .setM ...

  8. Android:数据存储之SQLite

    Android在运行时集成了SQLite , 所以每个Android应用程序都可以使用SQLite数据库. 我们通过SQLiteDatabase这个类的对象操作SQLite数据库,而且不需要身份验证. ...

  9. Android:设计之屏幕适配

    据统计目前市场Android手机的分辨率有是10余种,分辨率如此广泛使得我们在处理分辨率适应方便遇到不少难题,本文就此难点记录设计与实际布局中的解决技巧. 以320x480为蓝本设计布局 因为Andr ...

  10. Android:PopupWindow简单弹窗改进版

    Android:PopupWindow简单弹窗 继续上一节的内容,改进一下,目标是点击菜单后把菜单收缩回去并且切换内容,我使用的是PopupWindow+RadioGroup public class ...

随机推荐

  1. 【每日一题】【DFS】【BFS】【队列】2021年12月5日-199. 二叉树的右视图

    解答: /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * ...

  2. @Transactional注解事务失效的几种场景及原因

    1. 介紹 在业务开发的许多场景中,我们会使用到通过事务去控制多个操作的一致性.比较多的就是通过声明式事务,即使用 @Transactional 注解修饰方法的形式.但在使用过程中,要足够了解事务失效 ...

  3. (java 实现开箱即用基于 redis 的分布式锁

    项目简介 lock 为 java 设计的分布式锁,开箱即用,纵享丝滑. 开源地址:https://github.com/houbb/lock 目的 开箱即用,支持注解式和过程式调用 基于 redis ...

  4. MongoDB - 数据模型的设计模式

    简介 官方文章的地址是 Building with Patterns: A Summary,其中汇总了 12 种设计模式及使用场景. 上述的图表列举了 12 种设计模式及应用场景,主要是以下这些: 近 ...

  5. day08-功能实现07

    家居网购项目实现07 以下皆为部分代码,详见 https://github.com/liyuelian/furniture_mall.git 16.功能15-会员显示登录名 16.1需求分析/图解 会 ...

  6. 基于 Traefik 如何实现 path 末尾自动加斜杠?

    前言 Traefik 是一个现代的 HTTP 反向代理和负载均衡器,使部署微服务变得容易. Traefik 可以与现有的多种基础设施组件(Docker.Swarm 模式.Kubernetes.Mara ...

  7. Spark详解(01) - Scala编程语言

    Spark详解(01) - Scala编程语言概述 Scala官网:https://www.scala-lang.org/ 什么是Scala 从英文的角度来讲,Scala并不是一个单词,而是Scala ...

  8. B站地区限制破解方法

    B站地区限制破解方法 当我们观看bilibili番剧时,经常会看到"仅限港澳台地区"的字样.那么,有没有一种方法,不需要挂梯子,就可以观看这些被限制的番剧呢? 本教程只适用于bil ...

  9. 《Effective C++》构造、析构、赋值运算

    Item 05:了解C++默默编写并调用了哪些函数 总结:编译器可以暗自为class创建default 构造函数.copy构造函数.copy assignment操作符,以及析构函数. (这一小节比较 ...

  10. elasticsearch实现简单的脚本排序(script sort)

    目录 1.背景 2.分析 3.构建数据 3.1 mapping 3.2 插入数据 4.实现 4.1 根据省升序排序 4.1.1 dsl 4.1.2 运行结果 4.2 湖北省排第一 4.2.1 dsl ...