一、ViewModel介绍

ViewModel类是被设计用来以可感知生命周期的方式存储和管理 UI 相关数据。ViewModel中数据会一直存活即使 Activity Configuration发生变化。

ViewModel可以解决以下痛点。

1. 数据持久化

在屏幕旋转的时候会经历 Activity 的销毁与重新创建,这里就涉及到数据保存的问题,显然重新请求或加载数据是不友好的。在 ViewModel 出现之前我们可以用 Activity 的 onSaveInstanceState() 机制保存和恢复数据,但缺点很明显,onSaveInstanceState只适合保存少量的可以被序列化、反序列化的数据,这种机制明显不合适。
ViewModel 的设计思想可以解决此痛点。
 
ViewModel 生命周期图如下:

由图可知,ViewModel 生命周期是贯穿整个 activity 生命周期,包括 Activity 因旋转造成的重创建,直到 Activity 真正意义上销毁后才会结束。既然如此,用来存放数据再好不过了。

2. 异步回调问题

通常我们 App 需要频繁异步请求数据,比如调接口请求服务器数据。当然这些请求的回调都是相当耗时的,之前我们在 Activity 或 Fragment里接收这些回调。所以不得不考虑潜在的内存泄漏情况,比如 Activity 被销毁后接口请求才返回。处理这些问题,会给我们增添好多复杂的工作。但现在我们利用 ViewModel 处理数据回调,可以完美的解决此痛点。

3. 分担 UI controller 负担

从最早的 MVC 到目前流行的 MVP、MVVM,目的无非是 明确职责,分离 UI Controller 负担。

UI Controller 比如 Activity 、Fragment 是设计用来渲染展示数据、响应用户行为、处理系统的某些交互。如果再要求他去负责加载网络或数据库数据,会让其显得臃肿和难以管理。

所以为了简洁、清爽、丝滑,我们可以分离出数据操作的职责给 ViewModel。

4. Fragments 间共享数据

比如在一个 Activity 里有多个 Fragment,这 Fragment 之间需要做某些交互。我之前的做法是接口回调,需要统一在 Activity 里管理,并且不可避免的 Fragment 之间还得互相持有对方的引用。

仔细想想就知道这是很难搞的事情,耦合度高不说,还需要大量的容错判断。那么用 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 onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
itemSelector.setOnClickListener(item -> {
model.select(item);
});
}
} public class DetailFragment extends Fragment {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
model.getSelected().observe(this, { item ->
// Update the UI.
});
}
}
仔细体会下这样的好处会发现:
1. Activity 不需要做任何事,甚至不知道这次交互,完美解耦。
2. Fragment 只需要 与ViewModel交互,不需要知道对方 Fragment 的状态甚至是否存在,更不需要持有其引用。所有当对方 Fragment 销毁时,不影响本身任何工作。
3. Fragment 生命周期互不影响,甚至 fragment 替换成其他的 也不影响这个系统的运作。

二、ViewModel 的使用

ViewModel一般配合 LiveData 使用,首先,获取 ViewModel 实例,通过提供的类ViewModelProviders:

 MyViewModel model = ViewModelProviders.of(activity).get(MyViewModel.class);
// 或
MyViewModel model = ViewModelProviders.of(fragment).get(MyViewModel.class);

或带有 Factory 的

MyViewModel model = ViewModelProviders.of(activity,factory).get(MyViewModel.class);

ViewModel 内部操作如下:

public class MyViewModel extends ViewModel {
private MutableLiveData<List<User>> users;
public LiveData<List<User>> getUsers() {
if (users == null) {
users = new MutableLiveData<List<User>>();
loadUsers();
}
return users;
} private void loadUsers() {
// Do an asynchronous operation to fetch users.
}
}

然后,可在 Activity 观察数据变化:

public class MyActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
// Create a ViewModel the first time the system calls an activity's onCreate() method.
// Re-created activities receive the same MyViewModel instance created by the first activity. MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
model.getUsers().observe(this, users -> {
// update UI
});
}
}
 

Android框架式编程之ViewModel的更多相关文章

  1. Android框架式编程之Android Architecture Components

    1. 当前Android开发面临的问题 Android开发不同于传统的桌面程序开发,桌面程序一般都有唯一的快捷方式入口,并且常作为单进程存在:而一个典型的Android应用通常由多个应用组件构成,包括 ...

  2. Android框架式编程之BufferKnife

    配置 compile 'com.jakewharton:butterknife:(insert latest version)' annotationProcessor 'com.jakewharto ...

  3. Android框架式编程之Lifecycle

    Lifecycle官方文档地址:https://developer.android.com/topic/libraries/architecture/lifecycle. 一.为什么要使用Lifecy ...

  4. Android框架式编程之RxJava(一):HelloWorld

    Hello World 源码: import android.graphics.Bitmap; import android.graphics.BitmapFactory; import androi ...

  5. Android框架式编程之Room

    Room是Google官方出品的ORM(Object-relational mapping) 框架.当前我们也知道当前还有很多的ORM框架,例如GreenDao.OrmLite.Litepal等.目前 ...

  6. Android框架式编程之Retrofit

    一.Retrofit 简介 Retrofit 官网地址: https://github.com/square/retrofit Retrofit(即Retrofit,目前最新版本为2.6.0版本),是 ...

  7. Android框架式编程之LiveData

    一.LiveData 介绍 LiveData是 Google 推荐的 Android 架构组件之一,是一个基于观察者模式的数据容器,但与一般的被观察者不同的是,它是有生命周期感知功能,解决了Andro ...

  8. Android框架式编程之EasyPermissions

    EasyPermission库是一个谷歌官方提供的简化基本的系统权限逻辑的库,可用于在Android M或者更高版本上. 官方项目地址:https://github.com/googlesamples ...

  9. Android框架式编程之EventBus

    一.EventBus 简介 EventBus是一种用于Android的事件发布-订阅总线,由GreenRobot开发,Gihub地址是:EventBus. 它简化了应用程序内各个组件之间进行通信的复杂 ...

随机推荐

  1. 《手把手教你》系列进阶篇之1-python+ selenium自动化测试 - python基础扫盲(详细教程)

    1. 简介 如果你从一开始就跟着宏哥看博客文章到这里,基础篇和练习篇的文章.如果你认真看过,并且手动去敲过每一篇的脚本代码,那边恭喜你,至少说你算真正会利用Python+Selenium编写自动化脚本 ...

  2. 灵魂拷问:Java 的 substring() 是如何工作的?

    在逛 programcreek 的时候,我发现了一些小而精悍的主题.比如说:Java 的 substring() 方法是如何工作的?像这类灵魂拷问的主题,非常值得深入地研究一下. 另外,我想要告诉大家 ...

  3. 移动前端不得不了解的HTML5 head 头标签 —— link 标签

    目录 link 标签 rss订阅 不推荐的link标签 favicon 图标 link 标签 说到 link 标签,估计大家的第一反应和我一样,就是引入外部CSS样式文件的,不错,这是 link 标签 ...

  4. jQuery中的基本的选择器学习(补充版)

    先看整体代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <t ...

  5. asp.net core 配置微信返回信息接口

    这玩意弄了两天 微信的API需要升级了 只有一份PHP的DEMO 还有个坑 返回值一定要是 微信传入的echostr 否则 出现配置失败,这个问题耗了我俩小时 最后还是在论坛看到的解决方案. 项目必须 ...

  6. JS中&&和||的理解

    运算符可以从三个不同的层次进行理解. 第一层理解 当操作数都是布尔值时,"&&"对两个值执行布尔与(AND)操作. 复制代码代码如下: x==0 && ...

  7. [从今天开始修炼数据结构]图的最小生成树 —— 最清楚易懂的Prim算法和kruskal算法讲解和实现

    接上文,研究了一下算法之后,发现大话数据结构的代码风格更适合与前文中邻接矩阵的定义相关联,所以硬着头皮把大话中的最小生成树用自己的话整理了一下,希望大家能够看懂. 一.最小生成树 1,问题 最小生成树 ...

  8. Mysql Commands

    start service: mysqld --console; start client: mysql -uroot -proot; check server version: show varia ...

  9. Oracle GoldenGate for Sql Server连接ODBC失败的处理方法

    Oracle GoldenGate for Sql Server连接oracle数据库的时候还是比较容易的,命令行下面只要: GGSCI> dblogin useridalias [ alias ...

  10. 牛客NOIP暑期七天营-提高组5+普及组5

    ————提高组———— 第一题:deco的abs 题目链接:https://ac.nowcoder.com/acm/contest/934/A 因为每个数都可以加任意次 d ,所以可以推出 0 < ...