简介

  • 使用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,所以它可以保证数据不会丢失