传统的开发模式中,大多数的处理逻辑和数据都是写在Activity和Fragment,导致两者代码臃肿,因此产生了诸如MVP,MVVM的架构,而ViewModel正是实现MVVM架构最重要的组件之一。
ViewModel最重要的作用就是存放Activity和Fragment相关的数据,可以理解为存放页面所有数据的容器,那么问题来了,将数据和界面显示逻辑分开确实能让整体逻辑更清晰,但是为什么数据需要放在ViewModel,它和我们直接新建一个类来保存数据差别优点在哪?
其中使用ViewModel最重要的是它的生命周期并不是和Activity和Fragment完全同步,它生命周期更长,如下图,Activity/Fragment的onDestroy之外的其他生命周期都是ViewModel对象的生存期,只有Activity/Fragment销毁,ViewModel才会被销毁。最重要的是,正常手机横竖屏切换的时候Activity/Fragment需要被重建,同时数据也会清除,在这种重建过程中,Activity/Fragment会执行onDestroy操作,而ViewModel在这种情况下不会清除,只有Activity/Fragment退出时的onDestroy才会结束它的生命周期,因此ViewModel能更持久的保留数据。
通常情况下,建议一个Activity/Fragment对应一个ViewModel,界面保存各自的数据,ViewModel只提供数据的更改和获取操作,任何数据的逻辑处理都应该写在Activity/Fragment中。
为什么不能直接new的方式来新建ViewModel?因为ViewModel的生命周期和Activity/Fragment不一样,如果直接new的方式获得ViewModel,那么后者的生命周期将和前者完全同步
public class MyViewModel extends ViewModel {
int count = 0;
}
import androidx.lifecycle.ViewModelProvider; //1
public class MainActivity extends AppCompatActivity {
MyViewModel myViewModel;
TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
textView = findViewById(R.id.textview);
textView.setText(String.valueOf(++myViewModel.count));
}
}
[番外知识点]
有些同学在执行2的时候发现this下面报错,ViewModelProvider找不到对应的构造函数,这个原因主要是拓展库默认的是2.1.0的ViewModel版本,而在2.1.0的时候ViewModel只有下面两个构造函数
public ViewModelProvider(ViewModelStoreOwner owner, Factory factory) public ViewModelProvider(ViewModelStore store, Factory factory)
而在ViewModel2.2.0版本中新增了
public ViewModelProvider(@NonNull ViewModelStoreOwner owner)
因此只有显性的在模块gradle.build中引入2.2.0库即可
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
有参ViewModel的实例化
上述例子只能在无参ViewModel的实例化情况下才能使用,而由于生命周期的原因,有参ViewModel的实例化肯定也无法使用new的方式来获取ViewModel对象,因此需要借用实现了ViewModelProvider.Factory的类来实例化,具体来说,该接口的create不依赖Activity/Fragment的生命周期,因此可以使用create获得ViewModel对象
public class MyViewModel extends ViewModel {
int count = 0;
public MyViewModel(int count) {
this.count = count;
}
}
public class MyViewModelFactory implements ViewModelProvider.Factory {
int count = 0;
private MyViewModelFactory() {
}
public MyViewModelFactory(int count) {
this.count = count;
}
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
return (T) new MyViewModel(count);
}
}
public class MainActivity extends AppCompatActivity {
MyViewModel myViewModelFactory;
TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textview);
myViewModelFactory = new MyViewModelFactory(99).create(MyViewModel.class);
textView.setText(String.valueOf(++myViewModelFactory.count));
}
}
从上述例子我们可以归纳ViewModel的一些特征:
- ViewModel类似于一个数据类,作为具体数据存放的容器,生命周期由父类ViewModel掌控,自定义子类只需要关注数据的存取
- 建议一个Activity/Fragment对应一个ViewModel
- Activity/Fragment获取数据必须要获得自定义ViewModel对象,同时获取方式必须通过ViewModelProvider(无参情况)和ViewModelProvider.Factory对象(有参情况),以此来达到与Activity/Fragment不同的生命周期(具体实现逻辑请看后文源码分析)