Jetpack学习之 ViewModel

=======================================================================

导入参照: 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 使用后,打印结果为:

在这里插入图片描述

这里需要注意:

  1. ViewModel 绝不能引用视图、Lifecycle 或可能存储对 Activity 上下文的引用的任何类。 因为 ViewModel 存在的时间会比这些特定的实例更长。 它可以包含 LiveData 对象,但 ViewModel 绝对不能去观察它的更改。

如果 ViewModel 需要 Application 上下文,可以扩展 AndroidViewModel 用于接收 Application 的构造函数。

  1. 一个 Activity 上可以有多个 Fragment, 所以这些 Fragment 可以共享一个 ViewModel, 通过 ViewModelProvider 观察到两Fragment 都是处于同一个容器,那么就会为他们提供同一实例的 ViewModel

3. 原理

=======================================================================

3.1 ViewModel 的生命周期


ViewModel 的生命周期是贯穿了整个 Activity 的生命周期

在这里插入图片描述

您通常在系统首次调用 Activity 对象的 onCreate() 方法时请求 ViewModel。系统可能会在 Activity 的整个生命周期内多次调用 onCreate(),如在旋转设备屏幕时。ViewModel 存在的时间范围是从首次请求 ViewModel 直到 Activity 完成并销毁。

3.2 ViewModel的创建


我们可以从 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-JsQqDtOB-1715666074359)]

欢迎大家一起交流讨论啊~
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值