=======================================================================
导入参照: Jetpack学习之 Lifecycle
我们来自定义一个ViewModel,如下,它继承了 ViewModel
抽象类,在获取里面 LiveData 实例时,会去做一个耗时操作然后更新这个数据:
class MyViewModel : ViewModel() {
private val str: MutableLiveData by lazy {
MutableLiveData().also {
requestStr()
}
}
fun getStr(): LiveData {
return str
}
private fun requestStr() {
val executor = Executors.newSingleThreadExecutor()
executor.submit {
Thread.sleep(5000)
str.postValue(“Rikka”)
}
}
}
接着我们需要在 Activity 中使用它:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val model = ViewModelProvider(this).get(MyViewModel::class.java)
model.getStr().observe(this, Observer {
// 更新ui
Log.d(TAG, it)
})
}
获取 ViewModel 的方式有多种,除了上面代码中的 ViewModelProvider
, 还有 by viewModels()
等形式获取,需要相应的库来支持。
ViewModel 配合 LiveData 使用后,打印结果为:
这里需要注意:
- ViewModel 绝不能引用视图、Lifecycle 或可能存储对 Activity 上下文的引用的任何类。 因为 ViewModel 存在的时间会比这些特定的实例更长。 它可以包含 LiveData 对象,但
ViewModel
绝对不能去观察它的更改。
如果 ViewModel 需要 Application 上下文,可以扩展 AndroidViewModel
用于接收 Application 的构造函数。
- 一个 Activity 上可以有多个 Fragment, 所以这些 Fragment 可以共享一个 ViewModel, 通过 ViewModelProvider 观察到两Fragment 都是处于同一个容器,那么就会为他们提供同一实例的 ViewModel
=======================================================================
ViewModel 的生命周期是贯穿了整个 Activity 的生命周期
您通常在系统首次调用 Activity 对象的 onCreate()
方法时请求 ViewModel。系统可能会在 Activity 的整个生命周期内多次调用 onCreate(),如在旋转设备屏幕时。ViewModel 存在的时间范围是从首次请求 ViewModel 直到 Activity 完成并销毁。
我们可以从 ViewModelProvider(ViewModelStoreOwner).get(Class<T>)
入手:
public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
-
? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
- NewInstanceFactory.getInstance());
}
要求传入一个 ViewModelStroreOwner
, 而 ComponentActivity
/ Fragment
都实现了这个接口,这个接口只有一个函数 getViewModelStore()
, 所以实现的方法都会去创建一个 ViewModelStore
对象,它长这样:
public class ViewModelStore {
private final HashMap<String, ViewModel> mMap = new HashMap<>();
final void put(String key, ViewModel viewModel) {
ViewModel oldViewModel = mMap.put(key, viewModel);
if (oldViewModel != null) {
oldViewModel.onCleared();
}
}
final ViewModel get(String key) {
return mMap.get(key);
}
Set keys() {
return new HashSet<>(mMap.keySet());
}
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
}
这里面就是包含了一个 Map, k 是 String 也就是ViewModel 的名称, 而 value 就是 ViewModel 的实例。 再来看看 ViewModelProvider
的 get 方法:
public T get(@NonNull String key, @NonNull Class modelClass) {
// 1
ViewModel viewModel = mViewModelStore.get(key);
// 2
if (modelClass.isInstance(viewModel)) {
if (mFactory instanceof OnRequeryFactory) {
((OnRequeryFactory) mFactory).onRequery(viewModel);
}
return (T) viewModel;
} else {
if (viewModel != null) {
}
}:
if (mFactory instanceof KeyedFactory) {
viewModel = ((KeyedFactory) mFactory).create(key, modelClass);
} else {
// 3
viewModel = mFactory.create(modelClass);
}
// 4
mViewModelStore.put(key, viewModel);
return (T) viewModel;
}
注释1:从 ViewModelStore 的 Map 中去获取 ViewModel
注释2: 如果Map中获取到的 ViewModel 和 想要获取的类型一致,则返回这个实例
注释3、4:如果 Map中获取的为null,或者和想要获取的类型不一致,则通过 Factory.create()
创建一个实例,并将它传入到 Map 中。
这个 Factory 如果未指定, 一般就是 NewInstanceFactory
,来看看它的 create()
方法:
最后
如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足。谢谢。
欢迎大家一起交流讨论啊~
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!
这个 Factory 如果未指定, 一般就是 NewInstanceFactory
,来看看它的 create()
方法:
最后
如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足。谢谢。
[外链图片转存中…(img-CRL9RSJY-1715714654024)]
欢迎大家一起交流讨论啊~
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!