什么是 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. <五>模板的完全特例化和非完全特例化

    模板作为C++泛型编程的基础十分重要,其使得一份代码能用于处理多种数据类型.而有些时候,我们会希望对一些特定的数据类型执行不同的代码,这时就需要使用模板特例化(template specializat ...

  2. Window系统的mysql数据库定时备份

    原文:Window系统的mysql数据库定时备份 - Stars-One的杂货小窝 最近老大提到了数据库备份的功能,由于服务器是window系统的,所以研究了下备份的方案,特此记录 主要是实现每天定时 ...

  3. 第三方模块 request openpyxl

    目录 第三方模块的下载 pip工具 简介 pip使用注意 pip位置和环境变量设置 pip安装第三方模块 使用pip下载可能会遇到的问题 pycharm的第三方模块下载功能 request模块 req ...

  4. 成功解决pycharm 的setting中的Error occurred when installing package 'Keras'

    成功解决pycharm 的setting中的Error occurred when installing package 'Keras' 刚刚开始学习python在安装package上碰了不上壁. M ...

  5. 基于.NetCore开发博客项目 StarBlog - (22) 开发博客文章相关接口

    前言 本文介绍博客文章相关接口的开发,作为接口开发介绍的第一篇,会写得比较详细,以抛砖引玉,后面的其他接口就粗略带过了,着重于WebApi开发的周边设施. 涉及到的接口:文章CRUD.置顶文章.推荐文 ...

  6. Spring中11个最常用的扩展点,你知道几个?

    前言 在使用spring的过程中,我们有没有发现它的扩展能力很强呢? 由于这个优势的存在,使得spring具有很强的包容性,所以很多第三方应用或者框架可以很容易的投入到spring的怀抱中.今天我们主 ...

  7. JDBC的一些基础认识,写的不是特别完善,希望大家看的时候别太介意嘿嘿嘿

    JDBC 1,概念和本质 Java DataBase Connectivity Java 数据库链接, Java语言操作数据库 JDBC的本质:是一套操作所有关系型数据库的规则(接口)而JDBC所有的 ...

  8. [编程基础] Python命令行解析库argparse学习笔记

    Python argparse教程展示了如何使用argparse模块解析Python中的命令行参数. 文章目录 1 使用说明 1.1 Python argparse可选参数 1.2 Python ar ...

  9. CSS 奇思妙想之酷炫倒影

    在 CSS 中,倒影是一种比较常见的效果.今天,我们就将尝试,使用 CSS 完成各类不同的倒影效果,话不多说,直接进入主题. 实现倒影的两种方式 首先,快速过一下在 CSS 中,实现倒影的 2 种方式 ...

  10. iOS开发小结 - 通过PUT请求上传数据

    一般服务器上传数据一般都是用POST请求,这样通过AFNetworking的POST请求稳稳的,但是有一天遇到一个问题,服务器上传数据用的是PUT请求,发现用AFNetworking并不是那么好用,今 ...