内容简介:[译] Architecture Components 之 ViewModel
ViewModel
ViewModel 类是被设计用来存储和管理 UI 相关的数据,以便在配置更改(如:屏幕旋转)时数据可以保留下来。
注:在 Android 项目中导入ViewModel,请参阅添加组件到项目中
应用程序组件(如:activity 和 fragment)具有一个由 Android Framework 管理的生命周期。Framework 可能会完全不受控制的根据某些用户操作或设备事件来决定销毁或重新创建它们。
由于这些对象有可能被操作系统销毁或重新创建,所以保存在它们中的任何数据都会丢失。例如:如果 activity 中有一个用户列表,当 activity 因为配置更改而重新创建时,新的 activity 必须重新获取用户列表。对于简单的数据,activity 可以使用 onSaveInstanceState() 方法从onCreate() 中的 bundle 里恢复数据,但是这种方式只适用于少量数据(如:UI 状态),不适用于大量数据(如:用户列表)。
另一个问题是,这些 UI 控制器(activity,fragment 等)经常需要发起一些需要一定时间才能返回的异步调用。UI 控制器需要管理这些调用并且在其被销毁时清理它们避免潜在的内存泄漏。这需要大量的维护工作,并且在由于配置更改导致对象被重新创建的情况下十分浪费资源,因为需要重新发起相同的请求。
最后单也很重要的是,这些 UI 控制器已经需要完成响应用户操作和处理操作系统通信的工作了。当它们还需要手动处理其资源时,将会使类变的臃肿,创造“万能 activity”(或“万能 fragment”);也就是说,一个单独的类视图自己处理应用程序的所有工作,而不是将工作委派给其它类。这将会使测试非常困难。
将视图数据的所有权从 UI 控制器的逻辑中分离出来是简单高效的。Lifecycle 提供了一个叫ViewModel 的新类,一个 UI 控制器的帮助类,用来为 UI 准备数据。在配置更改期间,ViewModel 会自动保留,以便其保存的数据能够立即提供给下一个 activity 或 fragment 实例。在我们上面提到的例子中,获取并持有数据是 ViewModel 的责任,而不是 activity 或 fragment 的。
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() { // 执行异步操作获取用户 } }
现在 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 会调用ViewModel 的onCleared() 方法来清理资源。
注:由于ViewModel 存活的比个别的 activity 和 fragment 实例,所以它决不能引用 View,或任何持有 activity context 的引用的类。如果ViewModel 需要Application 的 context(如:调用系统服务),可以继承AndroidViewModel 类,可以在构造函数中接受Application(因为Application 继承了Context)。
在 Fragment 之间共享数据
activity 中的两个或多个 fragment 需要相互通信是很常见的。这不是个简单的事情,所有的 fragment 都需要定义一些接口秒素,并且拥有它们的 activity 必须将两者绑定在一起。另外,所有的 fragment 必须处理其它的 fragment 没有被创建或不可见的情况。
使用ViewModel 可以解决这个常见的痛点。假设一个主从式 fragment 的常见情况,用户从一个 fragment 的列表里选中一项,另一个 fragment 显示所选项的内容。
这些 fragment 可以使用其 activity 限定的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 -> // 更新 UI }); } }
请注意,在获取ViewModelProvider 时两个 fragment 都使用getActivity() 方法。这意味着它们都将会收到被 activity 限定的同一个 SharedViewModel 实例。
这种方式的优点有:
-
activity 不需要做或知道关于该通讯的任何事情。
-
除了 SharedViewModel 协议之外 fragment 不需要了解彼此。如果其中一个消失,另一个会照常工作。
-
每个 fragment 有自己的生命周期,并且不受其它 fragment 的生命周期影响。实际上,在 UI 中一个 fragment 替换另一个 fragment,UI 的运行没有任何问题。
ViewModel 的生命周期
在获取ViewModel 时,ViewModel 对象被传递给ViewModelProvider 的Lifecycle 限定。ViewModel 保留在内存中,直到限定它的Lifecycle 永久消失(当 activity 结束或 fragment 被分离)。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
视觉SLAM十四讲
高翔、张涛、等 / 电子工业出版社 / 2017-3 / 75
《视觉SLAM十四讲:从理论到实践》系统介绍了视觉SLAM(同时定位与地图构建)所需的基本知识与核心算法,既包括数学理论基础,如三维空间的刚体运动、非线性优化,又包括计算机视觉的算法实现,例如多视图几何、回环检测等。此外,还提供了大量的实例代码供读者学习研究,从而更深入地掌握这些内容。 《视觉SLAM十四讲:从理论到实践》可以作为对SLAM 感兴趣的研究人员的入门自学材料,也可以作为SLAM......一起来看看 《视觉SLAM十四讲》 这本书的介绍吧!