ViewModel是存储UI相关数据并不会因为旋转而销毁的类。
最为重要的就是ViewModel具有下面的生命周期,这就是ViewModel的最可贵之处:
下面写一个测试生命周期的demo:
Activity主要代码
public class MainActivity extends AppCompatActivity {
ActivityMainBinding mBinding;
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.e("mvvm_tag", "MainActivity onCreate");
super.onCreate(savedInstanceState);
mBinding = ActivityMainBinding.inflate(LayoutInflater.from(this));
setContentView(mBinding.getRoot());
mBinding.btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
FragmentOne fragmentOne = new FragmentOne();
Bundle bundle = new Bundle();
bundle.putString("content", "fragment one");
fragmentOne.setArguments(bundle);
getSupportFragmentManager()
.beginTransaction()
.addToBackStack("product")
.replace(R.id.content_1, fragmentOne, null).commit();
}
});
TestViewModel testViewModel = ViewModelProviders.of(this).get(TestViewModel.class);
}
@Override
protected void onStart() {
Log.e("mvvm_tag", "MainActivity onStart");
super.onStart();
}
@Override
protected void onResume() {
Log.e("mvvm_tag", "MainActivity onResume");
super.onResume();
}
@Override
protected void onPause() {
Log.e("mvvm_tag", "MainActivity onPause");
super.onPause();
}
@Override
protected void onStop() {
Log.e("mvvm_tag", "MainActivity onStop");
super.onStop();
}
@Override
protected void onDestroy() {
Log.e("mvvm_tag", "MainActivity onDestroy");
super.onDestroy();
}
}
public class TestViewModel extends AndroidViewModel {
public TestViewModel(@NonNull Application application) {
super(application);
}
@Override
protected void onCleared() {
Log.e("mvvm_tag", "TestViewModel onCleared");
super.onCleared();
}
}
Fragment主要代码
public class FragmentOne extends Fragment {
FragmentOneBinding mBinding;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Log.e("mvvm_tag", "FragmentOne onCreateView");
mBinding = FragmentOneBinding.inflate(LayoutInflater.from(getContext()));
return mBinding.getRoot();
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
Log.e("mvvm_tag", "FragmentOne onActivityCreated");
super.onActivityCreated(savedInstanceState);
OneViewModel oneViewModel = ViewModelProviders.of(this).get(OneViewModel.class);
oneViewModel.setContent(getArguments().getString("content"));
mBinding.setViewModel(oneViewModel);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
Log.e("mvvm_tag", "FragmentOne onViewCreated");
super.onViewCreated(view, savedInstanceState);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
Log.e("mvvm_tag", "FragmentOne onCreate");
super.onCreate(savedInstanceState);
}
@Override
public void onStart() {
Log.e("mvvm_tag", "FragmentOne onStart");
super.onStart();
}
@Override
public void onResume() {
Log.e("mvvm_tag", "FragmentOne onResume");
super.onResume();
}
@Override
public void onPause() {
Log.e("mvvm_tag", "FragmentOne onPause");
super.onPause();
}
@Override
public void onAttach(Context context) {
Log.e("mvvm_tag", "FragmentOne onAttach");
super.onAttach(context);
}
}
public class OneViewModel extends AndroidViewModel {
public ObservableField<String> content = new ObservableField<>();
public OneViewModel(@NonNull Application application) {
super(application);
}
@Override
protected void onCleared() {
Log.e("mvvm_tag", "OneViewModel onCleared");
}
public void setContent(String c) {
content.set(c);
}
}
布局如下:
点击显示:
操作一个完整流程:
启动app->点击“显示”->点击返回键->再次点击返回键关闭app
打印出来的log如下:
01-16 15:27:46.655 E/mvvm_tag: MainActivity onCreate
01-16 15:27:46.751 E/mvvm_tag: MainActivity onStart
01-16 15:27:46.753 E/mvvm_tag: MainActivity onResume
01-16 15:27:53.512 E/mvvm_tag: FragmentOne onAttach
01-16 15:27:53.512 E/mvvm_tag: FragmentOne onCreate
01-16 15:27:53.513 E/mvvm_tag: FragmentOne onCreateView
01-16 15:27:53.517 E/mvvm_tag: FragmentOne onViewCreated
01-16 15:27:53.517 E/mvvm_tag: FragmentOne onActivityCreated
01-16 15:27:53.519 E/mvvm_tag: FragmentOne onStart
01-16 15:27:53.519 E/mvvm_tag: FragmentOne onResume
01-16 15:28:16.485 E/mvvm_tag: FragmentOne onPause
01-16 15:28:16.485 E/mvvm_tag: OneViewModel onCleared
01-16 15:28:21.124 E/mvvm_tag: MainActivity onPause
01-16 15:28:21.601 E/mvvm_tag: MainActivity onStop
01-16 15:28:21.602 E/mvvm_tag: MainActivity onDestroy
01-16 15:28:21.603 E/mvvm_tag: TestViewModel onCleared
说明,在fragment中viewmodel与fragment的生命周期一致,而不是activity。
在activity中viewmodel与activity的生命周期一致。
下面测试屏幕旋转时,生命周期的变化。
启动app->点击“显示”->旋转屏幕
01-16 16:05:26.893 E/mvvm_tag: MainActivity onCreate
01-16 16:05:26.976 E/mvvm_tag: MainActivity onStart
01-16 16:05:26.977 E/mvvm_tag: MainActivity onResume
01-16 16:05:29.330 E/mvvm_tag: FragmentOne onAttach
01-16 16:05:29.331 E/mvvm_tag: FragmentOne onCreate
01-16 16:05:29.331 E/mvvm_tag: FragmentOne onCreateView
01-16 16:05:29.335 E/mvvm_tag: FragmentOne onViewCreated
01-16 16:05:29.335 E/mvvm_tag: FragmentOne onActivityCreated
01-16 16:05:29.335 E/mvvm_tag: FragmentOne onStart
01-16 16:05:29.336 E/mvvm_tag: FragmentOne onResume
// 旋转
01-16 16:05:39.520 E/mvvm_tag: MainActivity onPause
01-16 16:05:39.520 E/mvvm_tag: FragmentOne onPause
01-16 16:05:39.524 E/mvvm_tag: MainActivity onStop
01-16 16:05:39.525 E/mvvm_tag: MainActivity onDestroy
01-16 16:05:39.551 E/mvvm_tag: MainActivity onCreate
01-16 16:05:39.554 E/mvvm_tag: FragmentOne onAttach
01-16 16:05:39.554 E/mvvm_tag: FragmentOne onCreate
01-16 16:05:39.591 E/mvvm_tag: MainActivity onStart
01-16 16:05:39.591 E/mvvm_tag: FragmentOne onCreateView
01-16 16:05:39.594 E/mvvm_tag: FragmentOne onViewCreated
01-16 16:05:39.594 E/mvvm_tag: FragmentOne onActivityCreated
01-16 16:05:39.594 E/mvvm_tag: FragmentOne onStart
01-16 16:05:39.595 E/mvvm_tag: MainActivity onResume
01-16 16:05:39.598 E/mvvm_tag: FragmentOne onResume
可以看出,旋转屏幕时,activity和fragment都重新走了一遍生命周期,销毁之后重新创建,但是viewmodel并没有销毁重建。
这篇文字要弄清楚下面几个问题:
- ViewModel是怎么创建的?
- ViewModel是怎么存储的?
- ViewModel为什么可以实现旋转屏幕不销毁?
详情参考:【大揭秘】Android架构组件ViewModel来龙去脉
先放简单讲一下ViewModel的基本使用方法,我们在获取ViewModel的时候绝对不能直接使用new关键字去创建,需要使用 ViewModelProviders 去使用系统提供的反射方法去创建我们想要的ViewModel,下面是官方架构组件android.arch.lifecycle包下面的ViewModelProviders工具类用来获取ViewModel,才能与Activity或者Fragment的生命周期关联起来。
ViewModel 的存在是依赖 Activity 或者 Fragment的,不管你在什么地方获取ViewModel ,只要你用的是相同的Activity 或者 Fragment,那么获取到的ViewModel将是同一个 (前提是key值是一样的),所以ViewModel 也具有数据共享的作用!
一句话总结ViewModel是怎么被创建的:
创建一个ViewModelProvider,使用ViewModelProvider内部的全局单例AndroidViewModelFactory来反射创建 ViewModel,并把创建的ViewModel存入传入的ViewModelStore中!
到这里我们要知道:
- 第一: AndroidViewModelFactory在正常情况下是全局单例只有一个,只是一个反射创建对象的工具类。
- 第二:ViewModelProvider是每次获取创建ViewModel的时候都会创建一个新的。
- 第三:ViewModelStore是每一个Activity或者Fragment都有一个。
ViewModel是怎么被存储的
ViewModel是存储在当前Activity / Fragment的HolderFragment中的ViewModelStore的HashMap中,我们可以get,put或者在Activity / Fragment 销毁的时候HolderFragment会跟随销毁,在HolderFragment的onDestroy方法中调用mViewModelStore的clear方法。
ViewModel为什么可以实现旋转屏幕不销毁
setRetainInstance(boolean) 是Fragment中的一个方法。将这个方法设置为true就可以使当前Fragment在Activity重建时存活下来, 如果不设置或者设置为 false, 当前 Fragment 会在 Activity 重建时同样发生重建, 以至于被新建的对象所替代。
在setRetainInstance(boolean)为true的 Fragment (就是HolderFragment)中放一个专门用于存储ViewModel的Map, 这样Map中所有的ViewModel都会幸免于Activity的配置改变导致的重建,让需要创建ViewModel的Activity, Fragment都绑定一个这样的Fragment(就是HolderFragment), 将ViewModel存放到这个 Fragment 的 Map 中, ViewModel 组件就这样实现了。