Android架构组件(ViewMode概述)

努力尽今夕,少年犹可夸。这篇文章主要讲述Android架构组件:ViewMode概述相关的知识,希望能为你提供帮助。
作用:

ViewModel 类旨在以注重生命周期的方式存储和管理界面相关的数据。

问题:
(1) android 框架可以管理界面控制器(如 Activity, Fragment)的生命周期。由Android 框架响应的某些用户操作或设备事件,用户无法控制。 当系统销毁或重新创建界面控制器,则存储在其中的任何临时性界面相关数据都会丢失。对于简单的数据,Activity可以使用onSaveInstanceState()存储数据,组件重建后从onCreate()中的Bundle恢复其数据,但此方法仅适合可以序列化再反序列化的少量数据,如果数据量较大,如用户列表或位图,则不适合。(2)界面控制器经常需要进行异步调用,这些调用可能需要一些时间才能返回结果,有可能会出现UI组件已销毁,而请求还未返回的情况。在因配置更改而重新创建对象的情况下,对象可能需要重新发送请求,会造成资源的浪费(3)应该遵循职责分离原则,将视图数据从界面控制器逻辑中分离出来,这样不会导致界面控制器类代码膨胀

ViewModel的用法:
【Android架构组件(ViewMode概述)】架构组件为界面控制器提供了 ViewModel 辅助程序类,该类负责为界面准备数据。
在配置更改期间会自动保留 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< 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             });         }     }

如果Activity被重新创建了,它会收到被之前Activity创建的相同MyViewModel实例。当所属Activity终止后,框架调用ViewModel的onCleared()方法清除资源。
因为ViewModel在指定的Activity或Fragment实例外存活,它应该永远不能引用一个View,或持有任何包含Activity context引用的类。如果ViewModel需要Application的context(如获取系统服务),可以扩展AndroidViewmodel,并拥有一个构造器接收Application。

ViewModel 的生命周期
ViewModel 对象存在的时间范围是获取ViewModel时传递给ViewModelProvider的Lifecycle。ViewModel将一直留在内存中,直到限定其存在时间范围的Lifecycle 永久消失:对于 Activity,是在Activity完成时;而对于Fragment,是在Fragment分离时。
Android架构组件(ViewMode概述)

文章图片

上图左侧为Activity的生命周期过程,期间有一个旋转屏幕的操作;右侧则为ViewModel的生命周期过程。
一般通过如下代码初始化ViewModel:
viewModel = ViewModelProviders.of(this).get(UserProfileViewModel.class); // this参数一般为Activity或Fragment,因此ViewModelProvider可以获取组件的生命周期。

Activity在生命周期中可能会触发多次onCreate(),而ViewModel则只会在第一次onCreate()时创建,然后直到最后Activity销毁。
在Fragment间共享数据
一个Activity中的多个Fragment相互通讯是很常见的。假设有一个Fragment,在该Fragment 中,用户从列表中选择一项,还有另一个Fragment,用于显示选定项的内容。这种情况不太容易处理,因为这两个 Fragment都需要定义某种接口描述,并且所有者Activity必须将两者绑定在一起。此外,这两个 Fragment 都必须处理另一个Fragment尚未创建或不可见的情况。
可以使用 ViewModel 对象解决这一常见的难点。这两个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 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.             });         }     }

注意:这两个Fragment都会检索包含它们的Activity。这样,当这两个Fragment各自获取ViewModelProvider时,它们会收到相同的SharedViewModel实例(其范围限定为该Activity)。
此方法具有以下优势:
* Activity 不需要执行任何操作,也不需要对此通信有任何了解。 * 除了SharedViewModel约定之外,Fragment不需要相互了解。如果其中一个Fragment 消失,另一个Fragment将继续照常工作。 * 每个Fragment 都有自己的生命周期,而不受另一个Fragment的生命周期的影响。如果一个Fragment替换另一个Fragment,界面将继续工作而没有任何问题。

参考:
https://developer.android.google.cn/topic/libraries/architecture/viewmodel.html#java
https://blog.csdn.net/qq_24442769/article/details/79426609
https://blog.csdn.net/zhuzp_blog/article/details/78910535


    推荐阅读