Android官方架构组件介绍之ViewModel
ViewModel
像Activity,Fragment这类应用组件都有自己的生命周期并且是被Android的Framework所管理的。Framework可能会根据用户的一些操作和设备的状态对Activity或者Fragment进行销毁和重构。作为开发者,这些行为我们是无法干预的。
所以Activity或Fragment中的一些数据也会随着销毁而丢失,随着重构而重新生成。比如你的Activity中有个用户列表,当这个Activity重构的时候,新的Activity会重新获取用户列表。对于一些简单的数据,Activity可以使用onSaveInstanceState()方法,并从onCreate的bundle中重新获取。但这一方法途径仅仅适合一些简单的UI状态,对于用户列表这种庞大的数据并不适合。
还存在一个问题,Activity或者Fragment经常会做一些异步的耗时操作。随之就需要Activity和Fragment管理这些异步操作,并在自己被destroyed的时候清理它们,从而保证内存溢出这类问题的发生。这样的处理会随着项目扩大而变得十分复杂,一不留神,你的App就Crash了。
Activity和Fragment本身需要处理很多用户的输入事件并和操作系统打交道,所以当它们还要花时间管理它们的数据资源时,class文件就会变得异常庞大,然后就会造就出所谓的god activities和god fragments。这些UI控制类仅仅靠一个class就能处理相关的所有事务。简直跟上帝没啥两样。但这些类如果要进行单元测试的话,那就尴尬了。
所以就有了MVC,MVP这类设计模式,将视图与数据分离。今天讲到的ViewModel类的功能也一样,就是讲数据从UI中分离出来。并且当Activity或Fragment重构的时候,ViewModel会自动保留之前的数据并给新的Activity或Fragment使用。对于上面提到的用户列表的例子,ViewModel会为我们很好的管理这些数据。
public class MyViewModel extends ViewModel {
private MutableLiveData<List<User>> users;
public LiveData<List<User>> getUsers() {
if (users == null) {
users = new MutableLiveData<List<Users>>();
loadUsers();
}
return users;
}
private void loadUsers() {
// do async operation to fetch users
}
}
接着在我们的Activity中就能这样使用了:
public class MyActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
model.getUsers().observe(this, users -> {
// update UI
});
}
}
这是当MyActivity被重构时,获得到的model实例是与重构前同一个,当MyActivity被销毁时,Framework会调用ViewModel的onCleared(),我们就可以在此方法中做资源的清理。
因为ViewModel的生命周期是和Activity或Fragment分开的,所以在ViewModel中绝对不能引用任何View对象或者任何引用了Activity的Context的对象。如果ViewModel中需要Application的Context的话,可以继承
AndroidViewModel。
Fragment之间的数据共享
在Activity中包好多个Fragment并且需要相互通信是非常常见的,这时就需要这些Fragment定义一些接口,然后让Activity来进行协调。而且这些Fragment还需要处理其他Fragment不可见或者还没有创建这些细节问题。
上面这个动点可以被ViewModel轻易解决,想象意向有这么个Activity,它包含FragmentA和FragmentB,其中A是用户列表,B是用户的详细数据,点击列表上的某个用户,在B中显示相应的数据。
看看使用ViewModel怎么处理这个问题:
public class SharedViewModel extends ViewModel {
private final MutableLiveData<Item> selected = new MutableLiveData<Item>();
public void select(Item item) {
selected.setValue(item);
}
public LiveData<Item> getSelected() {
return selected;
}
}
public class MasterFragment extends Fragment {
private SharedViewModel model;
public void onActivityCreated() {
model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
itemSelector.setOnClickListener(item -> {
model.select(item);
});
}
}
public class DetailFragment extends LifecycleFragment {
public void onActivityCreated() {
SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
model.getSelected().observe(this, { item ->
// update UI
});
}
}
这里要注意的是两个Fragment都使用了getActivity作为参数来获得ViewModel实例。这表示这两个Fragment获得的ViewModel对象是同一个。
使用了ViewModel的好处如下:
- Activity不需要做任何事情,不需要干涉这两个Fragment之间的通信。
- Fragment不需要互相知道,即使一个消失不可见,另一个也能很好的工作。
- Fragment有自己的生命周期,它们之间互不干扰,即便你用一个FragmentC替代了B,FragmentA也能正常工作,没有任何问题。
ViewModel的生命周期
ViewModel的生命周期跟着传递给ViewModelProvider的LifeCycle走,当生成了ViewModel的实例后,它会一直待在内存中,直到对应的LifeCycle彻底结束。下面是ViewModel与Activity对应的生命周期图:

Android官方架构组件介绍之ViewModel的更多相关文章
- Android官方架构组件介绍之ViewModel(三)
ViewModel 像Activity,Fragment这类应用组件都有自己的生命周期并且是被Android的Framework所管理的.Framework可能会根据用户的一些操作和设备的状态对Act ...
- Android官方架构组件介绍之LifeCycle(一)
Android官方架构组件介绍之LifeCycle 下面是官方提供的Android App开发的架构图: 从上图可以看到一些关键字:ViewModel,LiveData,Room等.其实看了上面视频的 ...
- Android官方架构组件介绍之LifeCycle
Google 2017 I/O开发者大会于近日召开,在开发者大会上谷歌除了发布了Android O等一些新产品之外,也对Android代码的架构做出了一个官方的回应. Google 2017 I/O开 ...
- Android官方架构组件介绍之LiveData
LiveData LiveData是一个用于持有数据并支持数据可被监听(观察).和传统的观察者模式中的被观察者不一样,LiveData是一个生命周期感知组件,因此观察者可以指定某一个LifeCycle ...
- Android官方架构组件介绍之LiveData(二)
LiveData LiveData是一个用于持有数据并支持数据可被监听(观察).和传统的观察者模式中的被观察者不一样,LiveData是一个生命周期感知组件,因此观察者可以指定某一个LifeCycle ...
- Android官方架构组件介绍之应用(四)
讲一个项目常见的功能,友盟统计功能 例如一个项目有很多多modlue,每个里面modlue都有Activity,Activity需要友盟统一,Fragment也需要友盟统计.一般做法就是继承一个Bas ...
- 改造 Android 官方架构组件 ViewModel
前言 Android 官方架构组件在今年 5 月份 Google I/O 大会上被公布, 直到 11 月份一直都是测试版, 由于工作比较繁忙, 期间我只是看过类似的文章, 但没有在实际项目中使用过, ...
- Android官方架构组件指南
此指南适用于那些曾经或现在进行Android应用的基础开发,并希望了解和学习编写Android程序的最佳实践和架构.通过学习来构建强大的生产级别的应用. 注意:此指南默认你对Android开发有比较深 ...
- Jetpack架构组件学习(2)——ViewModel和Livedata使用
要看本系列其他文章,可访问此链接Jetpack架构学习 | Stars-One的杂货小窝 原文地址:Jetpack架构组件学习(2)--ViewModel和Livedata使用 | Stars-One ...
随机推荐
- C# 属性事件一些设置说明
大致列举一些常用的属性或事件的一些修饰 用法类似,主要是对属性的进一步设置 [Browsable(true)] public bool Enable {get;set;} 顺便说一下事件的应用: pu ...
- Sublime Text 3安装清爽主题(著名的Soda Theme)
Sublime Text是一款强大的编辑器,不但拥有众多强大的功能,还拥有很多漂亮的主题以及大量的插件可供配置使用. 本文主要描述Sublime Text 3安装清爽的主题,默认的深色主题Monoka ...
- jQuery-替换和删除元素
1.replaceWith方法 用提供的内容替换集合中所有匹配的元素并且返回被替换元素的集合 参数类型说明: 1)普通字符串(可包含各种html标签) 2)jQuery对象 ①使用$函数创建的新元素( ...
- 详解JavaScript的splice()方法
from:http://www.jquerycn.cn/a_10447 在javascript中splice()方法,是一个很强的数组方法,它有多种用法.splice()主要用途是向数组的中部插入项. ...
- Animy.js,自己编写的功能丰富的html动画库
近期由于项目须要.本人制作了一款js的动画插件.能够用于完毕各种js动画.比方移动.拉升.变色等等,全部动画经常使用的功能都已经实现,比方播放.暂停.停止.循环.加速.减速.反向播放.缓动.路径动画. ...
- Swift-基础语法之变量&常量&元组
使用 let来声明一个常量,用 var来声明一个变量.常量的值在编译时并不要求已知,但是你必须为其赋值一次.这意味着你可以使用常量来给一个值命名,然后一次定义多次使用 myVariable = let ...
- ArcGIS 要素合并
1.选择工具 2.选择输入要素.输出要素.按照什么字段进行合并 3.查看融合结果 4.GP工具-创建GP模型 拖入“融合”工具,设置融合的参数,如下图: 右击左边椭圆,勾选 模型参数 右击右边椭圆,勾 ...
- shell基础篇(二)-shell变量
1. 定义变量 1).定义变量时,变量名不加美元符号($),如: var="hello world"2).注意,变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样.同 ...
- 在map中一个key中存多个值
一说到map都想到key-value键值队存在.key可以为最多一个null的key. 今天开发中一个业务需求,在map中一个key中存多个对象. 我首先想到Map<String,List> ...
- oracle12c创建用户和表空间出现的问题
Oracle12c 中,增加了可插接数据库的概念,即PDB,允许一个数据库容器(CDB)承载多个可插拔数据库(PDB).CDB全称为 ContainerDatabase,中文翻译为数据库容器,PDB全 ...