博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[译] Architecture Components 之 ViewModel
阅读量:6229 次
发布时间:2019-06-21

本文共 3315 字,大约阅读时间需要 11 分钟。

【目录】

1.

2.

3.

4.

5.

6.

ViewModel

类是被设计用来存储和管理 UI 相关的数据,以便在配置更改(如:屏幕旋转)时数据可以保留下来。

注:在 Android 项目中导入 ,请参阅

应用程序组件(如:activity 和 fragment)具有一个由 Android Framework 管理的生命周期。Framework 可能会完全不受控制的根据某些用户操作或设备事件来决定销毁或重新创建它们。

由于这些对象有可能被操作系统销毁或重新创建,所以保存在它们中的任何数据都会丢失。例如:如果 activity 中有一个用户列表,当 activity 因为配置更改而重新创建时,新的 activity 必须重新获取用户列表。对于简单的数据,activity 可以使用 方法从 中的 bundle 里恢复数据,但是这种方式只适用于少量数据(如:UI 状态),不适用于大量数据(如:用户列表)。

另一个问题是,这些 UI 控制器(activity,fragment 等)经常需要发起一些需要一定时间才能返回的异步调用。UI 控制器需要管理这些调用并且在其被销毁时清理它们避免潜在的内存泄漏。这需要大量的维护工作,并且在由于配置更改导致对象被重新创建的情况下十分浪费资源,因为需要重新发起相同的请求。

最后单也很重要的是,这些 UI 控制器已经需要完成响应用户操作和处理操作系统通信的工作了。当它们还需要手动处理其资源时,将会使类变的臃肿,创造“万能 activity”(或“万能 fragment”);也就是说,一个单独的类视图自己处理应用程序的所有工作,而不是将工作委派给其它类。这将会使测试非常困难。

将视图数据的所有权从 UI 控制器的逻辑中分离出来是简单高效的。Lifecycle 提供了一个叫 的新类,一个 UI 控制器的帮助类,用来为 UI 准备数据。在配置更改期间, 会自动保留,以便其保存的数据能够立即提供给下一个 activity 或 fragment 实例。在我们上面提到的例子中,获取并持有数据是 ViewModel 的责任,而不是 activity 或 fragment 的。

public class MyViewModel extends ViewModel {    private MutableLiveData
> users; public LiveData
> getUsers() { if (users == null) { users = new MutableLiveData
>(); loadUsers(); } return users; } private void loadUsers() { // 执行异步操作获取用户 }}复制代码

现在 activity 可以像下面这样访问列表:

public class MyActivity extends AppCompatActivity {    public void onCreate(Bundle savedInstanceState) {        MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);        model.getUsers().observe(this, users -> {            // 更新 UI        });    }}复制代码

如果 activity 被重新创建,它将会收到由之前 activity 创建的同一个 MyViewModel 实例。当所有者 activity 结束后,Framework 会调用 的 方法来清理资源。

注:由于 存活的比个别的 activity 和 fragment 实例,所以它决不能引用 View,或任何持有 activity context 的引用的类。如果 需要 的 context(如:调用系统服务),可以继承 类,可以在构造函数中接受 (因为 继承了 )。

在 Fragment 之间共享数据

activity 中的两个或多个 fragment 需要相互通信是很常见的。这不是个简单的事情,所有的 fragment 都需要定义一些接口秒素,并且拥有它们的 activity 必须将两者绑定在一起。另外,所有的 fragment 必须处理其它的 fragment 没有被创建或不可见的情况。

使用 可以解决这个常见的痛点。假设一个主从式 fragment 的常见情况,用户从一个 fragment 的列表里选中一项,另一个 fragment 显示所选项的内容。

这些 fragment 可以使用其 activity 限定的 来处理该通讯。

public class SharedViewModel extends ViewModel {    private final MutableLiveData
selected = new MutableLiveData
(); public void select(Item item) { selected.setValue(item); } public LiveData
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 -> // 更新 UI }); }}复制代码

请注意,在获取 时两个 fragment 都使用 方法。这意味着它们都将会收到被 activity 限定的同一个 SharedViewModel 实例。

这种方式的优点有:

  • activity 不需要做或知道关于该通讯的任何事情。

  • 除了 SharedViewModel 协议之外 fragment 不需要了解彼此。如果其中一个消失,另一个会照常工作。

  • 每个 fragment 有自己的生命周期,并且不受其它 fragment 的生命周期影响。实际上,在 UI 中一个 fragment 替换另一个 fragment,UI 的运行没有任何问题。

ViewModel 的生命周期

在获取 时, 对象被传递给 的 限定。 保留在内存中,直到限定它的 永久消失(当 activity 结束或 fragment 被分离)。

转载地址:http://vcxna.baihongyu.com/

你可能感兴趣的文章
golang array, slice, string笔记
查看>>
java 集合、接口
查看>>
AutoMapper用法
查看>>
维护后面的position + 离线 + 线段树 bzoj 3585
查看>>
StringUtils常用方法+StringUtils详细介绍
查看>>
iOS开发之JSON解析
查看>>
iOS开发之Run Loop
查看>>
PDF 补丁丁 0.5.0.2731 发布(增加去除页面表单和链接水印功能)
查看>>
PDF 补丁丁 0.6.0.3355 版发布(修复阅读模式、书签缩放的问题)
查看>>
python 内嵌模块——time
查看>>
关于form与表单操作
查看>>
网络协议
查看>>
同源策略
查看>>
Date——时间戳转化为YYYY-MM-DD h:m:s时间格式
查看>>
MySQL_PHP学习笔记_2015_0907_PHP用pdo连接数据库时报错 could not find driver
查看>>
字符类型
查看>>
Algs4-1.1.5位于0与1之间则打印true,否则打印false
查看>>
分布式存储 FastDFS-5.0.5线上搭建
查看>>
[Java 基础]ResultSet 指定field映射到Pojo对象的Map
查看>>
Oracle 11g OCM 考试大纲
查看>>