Jetpack -- ViewModel使用与分析
原创
©著作权归作者所有:来自51CTO博客作者wx5ba8dc11102bc的原创作品,请联系作者获取转载授权,否则将追究法律责任
简介
- 使用Android AAC组件构建自己的应用之后,为了不让自己停留在仅仅是使用的层面,所以从头开始总结一边AAC组件的使用以及注意的要点
- ViewModel旨在以注重生命周期的方式存储和管理界面相关的数据, ViewModel 类让数据可在发生屏幕旋转等配置更改后继续存在
作用:
- 将View中的数据模块进行单独的管理,使得Activity和Fragment更加简单,只需要专注于界面本身不需要管理界面复杂的数据
- 使用ViewModel的意义在于,平时当一个界面create或者destory的时候,我们需要使用onSaveInstanceState()从onCreate()中的捆绑包回复其数据,但是当数据较大且序列化、反序列化较困难的时候,当采用ViewModel时候,数据是不会丢失的
- 同时针对某些业务中的异步回调,我们可以利用ViewModel处理数据回调来解决这个问题
ViewModel使用
class MyViewModel : ViewModel() {
public var number : Int = 0
}
class MainActivity : AppCompatActivity() {
private lateinit var myViewModel: MyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
// 首次调用onCreate时创建一个ViewModel ,重新创建的活动也会接受第一次创建的MyViewModel的实例,从而保证数据的一致性
myViewModel = ViewModelProviders.of(this).get(MyViewModel::class.java)
button.setOnClickListener({
myViewModel.number++
textView.setText(myViewModel.number.toString())
})
button2.setOnClickListener({
myViewModel.number += 2
textView.setText(myViewModel.number.toString())
})
textView.setText(myViewModel.number.toString())
}
}
- 当Activity finish的时候,框架会调用ViewModel的onCleared()方法来清理资源
ViewModel生命周期
- ViewModel生命周期是贯穿整个activity生命周期,包括Activity因旋转造成的重创建,直到Activity销毁才会结束
使用ViewModel在Fragment之间共享数据
- 之前在项目中如果两个fragment需要通信,就会在Activity中将两者绑定在一起,并且fragment之间还需要互相持有对方的引用
- 使用ViewModel之后两个fragment可以通过ViewModel关联起来实现数据在两个fragment之间的共享
class SharedViewModel : ViewModel() {
val selected = MutableLiveData<Item>()
fun select(item: Item) {
selected.value = item
}
}
class MasterFragment : Fragment() {
private lateinit var itemSelector: Selector
private lateinit var model: SharedViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
model = activity?.run {
ViewModelProviders.of(this)[SharedViewModel::class.java]
} ?: throw Exception("Invalid Activity")
itemSelector.setOnClickListener { item ->
// Update the UI
}
}
}
class DetailFragment : Fragment() {
private lateinit var model: SharedViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
model = activity?.run {
ViewModelProviders.of(this)[SharedViewModel::class.java]
} ?: throw Exception("Invalid Activity")
model.selected.observe(this, Observer<Item> { item ->
// Update the UI
})
}
}
如何保证数据不会丢失
首先我们创建ViewModel
ViewModelProviders.of(this).get(MyViewModel::class.java)
of和get方法
public static ViewModelProvider of(@NonNull FragmentActivity activity,
@Nullable Factory factory) {
if (factory == null) {
factory = activity.getDefaultViewModelProviderFactory();
}
return new ViewModelProvider(activity.getViewModelStore(), factory);
}
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
// 通过key从viewModelStore中取出viewModel
ViewModel viewModel = mViewModelStore.get(key);
// 横屏或者重建判断取出的viewmodel和传入的viewmodel的类型是否一致
if (modelClass.isInstance(viewModel)) {
if (mFactory instanceof OnRequeryFactory) {
// 重新查询该ViewModel
((OnRequeryFactory) mFactory).onRequery(viewModel);
}
return (T) viewModel;
} else {
//noinspection StatementWithEmptyBody
if (viewModel != null) {
// TODO: log a warning.
}
}
if (mFactory instanceof KeyedFactory) {
viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);
} else {
viewModel = (mFactory).create(modelClass);
}
// 初始进入将ViewModel保存在viewmodelstore中
mViewModelStore.put(key, viewModel);
return (T) viewModel;
}
- 从上面的代码可以分析出,Activity的销毁重建都是从ViewModelStore中获取的ViewModel----获得的是同一个ViewModel,所以它可以保证数据不会丢失