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 activitiesgod 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的生命周期跟着传递给ViewModelProviderLifeCycle走,当生成了ViewModel的实例后,它会一直待在内存中,直到对应的LifeCycle彻底结束。下面是ViewModel与Activity对应的生命周期图:

转自https://www.cnblogs.com/zqlxtt/p/6888507.html

Android官方架构组件介绍之ViewModel(三)的更多相关文章

  1. Android官方架构组件介绍之ViewModel

    ViewModel 像Activity,Fragment这类应用组件都有自己的生命周期并且是被Android的Framework所管理的.Framework可能会根据用户的一些操作和设备的状态对Act ...

  2. Android官方架构组件介绍之LifeCycle(一)

    Android官方架构组件介绍之LifeCycle 下面是官方提供的Android App开发的架构图: 从上图可以看到一些关键字:ViewModel,LiveData,Room等.其实看了上面视频的 ...

  3. Android官方架构组件介绍之LifeCycle

    Google 2017 I/O开发者大会于近日召开,在开发者大会上谷歌除了发布了Android O等一些新产品之外,也对Android代码的架构做出了一个官方的回应. Google 2017 I/O开 ...

  4. Android官方架构组件介绍之LiveData

    LiveData LiveData是一个用于持有数据并支持数据可被监听(观察).和传统的观察者模式中的被观察者不一样,LiveData是一个生命周期感知组件,因此观察者可以指定某一个LifeCycle ...

  5. Android官方架构组件介绍之LiveData(二)

    LiveData LiveData是一个用于持有数据并支持数据可被监听(观察).和传统的观察者模式中的被观察者不一样,LiveData是一个生命周期感知组件,因此观察者可以指定某一个LifeCycle ...

  6. Android官方架构组件介绍之应用(四)

    讲一个项目常见的功能,友盟统计功能 例如一个项目有很多多modlue,每个里面modlue都有Activity,Activity需要友盟统一,Fragment也需要友盟统计.一般做法就是继承一个Bas ...

  7. 改造 Android 官方架构组件 ViewModel

    前言 Android 官方架构组件在今年 5 月份 Google I/O 大会上被公布, 直到 11 月份一直都是测试版, 由于工作比较繁忙, 期间我只是看过类似的文章, 但没有在实际项目中使用过, ...

  8. Android官方架构组件指南

    此指南适用于那些曾经或现在进行Android应用的基础开发,并希望了解和学习编写Android程序的最佳实践和架构.通过学习来构建强大的生产级别的应用. 注意:此指南默认你对Android开发有比较深 ...

  9. Jetpack架构组件学习(2)——ViewModel和Livedata使用

    要看本系列其他文章,可访问此链接Jetpack架构学习 | Stars-One的杂货小窝 原文地址:Jetpack架构组件学习(2)--ViewModel和Livedata使用 | Stars-One ...

随机推荐

  1. Django models模型ORM

    一.ORM介绍 映射关系: 表名 -------------------->类名 字段-------------------->属性 表记录----------------->类实例 ...

  2. 37LCD-TFTLCD原理与配置

    1.TFTLCD驱动原理 简介

  3. Java50道经典习题-程序30 插入数字

    题目:有一个已经排好序的数组.现输入一个数,要求将它插入数组中后数组依然是排好序的.分析:首先判断此数是否大于最后一个数,然后再考虑插入中间的数的情况,插入后此元素之后的数,依次后移一个位置. imp ...

  4. jQuery 插件开发——GridData(表格)第二版

    开发背景 表格插件之前我也写个一篇,当时写那个插件的时候,我自己还没有总结出写插件的方法,虽然功能实现了,但是使用起来还是有点别扭的,并且需要在调用写添加特定名称的方法,这个地方着实违背了开发插件的易 ...

  5. 如何选择SSL 证书服务

    从信任等级的角度来说,SSL证书主要分为三类: 1. 域名型https证书(DVSSL):信任等级一般,只需验证网站的真实性便可颁发证书保护网站: 2. 企业型https证书(OVSSL):信任等级高 ...

  6. JavaScript之DOM HTML

    前言 JavaScript这门语言在一定程度上让我们html之间耦合度降低了,为什么这样说呢?JavaScript语言一样可以可以随意写入html页面一些东西,比如:JavaScript的DOM可以改 ...

  7. 【BZOJ 3326】[Scoi2013]数数

    题目描述 Fish 是一条生活在海里的鱼,有一天他很无聊,就开始数数玩.他数数玩的具体规则是: 确定数数的进制B 确定一个数数的区间[L, R] 对于[L, R] 间的每一个数,把该数视为一个字符串, ...

  8. P2770 航空路线问题

    \(\color{#0066ff}{题目描述}\) 给定一张航空图,图中顶点代表城市,边代表 2 城市间的直通航线.现要求找出一条满足下述限制条件的且途经城市最多的旅行路线. (1)从最西端城市出发, ...

  9. POI精确设置Excel的行高和列宽

    EXCEL的行高度和列宽度单位是不一样的. 1,EXCEL列高度的单位是磅,Apache POI的行高度单位是缇(twip): 1英寸=72磅=25.4毫米=1440缇1磅=0.353毫米=20缇 P ...

  10. Qt 学习之路 2(6):Qt 模块简介

    Home / Qt 学习之路 2 / Qt 学习之路 2(6):Qt 模块简介  豆子  2012年8月26日  Qt 学习之路 2  20条评论 Qt 5 与 Qt 4 最大的一个区别之一是底层架构 ...