欢迎光临散文网 会员登陆 & 注册

Coroutine 学习(二)ViewModelScope LifeCycleScope Dispatcher

2021-09-29 11:18 作者:房顶上的铝皮水塔  | 我要投稿

问题:

  1. koin如何创建ViewModel?

  2. ViewModelScope和LifeCycleScope的最佳使用方式是什么?

  3. ViewModel和Repository使用方式是什么 各自的职责是什么?

  4. Room和ViewModel应该如何配合使用

  5. 单独使用supsend函数,suspend函数表示的协程和它所在的CoroutineScope的生命周期相同吗?

  6. 我们所使用的Dispatchers.Main IO 是一个【单例】吗?

Koin

首先需要明确module, Service, scope这些概念和我们之前所了解的都不同,在谈及Koin的上下文时,这些都是Koin定义的概念

Koin使用步骤

Koin是一种实现依赖注入的方式,使用的时候需要遵循的步骤

  1. 定义KoinModule

    2. 在application中注册:

Service的创建:

factory single viewModel都可以创建Service到Module中


生命周期

Service的创建方式还指定了Service的生命周期。可以自定义Scope的生命周期

依赖注入方式:

1. get

定义在module中的类需要参数,可以通过get声明参数。Koin会在module中寻找是否存在对应的Service

在其他地方也可以通过get方法获取实例:

2. 懒加载inject


在Android中使用协程的最佳做法:

https://developer.android.google.cn/kotlin/coroutines/coroutines-best-practices?hl=zh-cn

在Android ViewModel中使用协程的最佳方式

在ViewModel中使用协程的一个方式是使用viewModelScope,因为遵循了结构化并发思想。

结构化并发:

内容:使得每一个协程都运行在指定的CoroutineScope中

为什么要这么做:

  1. 是我们的每一个suspend、协程都不会产生lost or leak

  2. 保证所有的异常都能够正确的处理

对于lost和leak的理解:

因为所有的协程的生命都在一个上下文中,所以只要管理好上文的Scope,内部的协程也可以被管理,当关闭父协程(外面的scope)时,内部的子协程也会被关闭。

ViewModel的生命周期


ViewModel的生命周期和创建它时传入的LifeCycle组件的生命周期有关。使用viewScope我们能在viewScope中开启协程也不用担心内存泄漏:


viewModelScope = SupervisorJob + Dispatchers.Main.immediate

当ViewModel生命周期走到尽头时,会调用clear方法其中又会调用closeWithRuntimeException。因为viewModelScope又是一个CloseCoroutineScope,所以可以使用closeWithRuntimeException方法关闭。Dispatchers.Main.immediate判断如果当前在主线程,立马执行协程,不会通过Dispatcher再分发。

对于ViewModel职责的理解

ViewModel应该是连接View和Model的桥梁。所以viewModelscope是在Main调度器上运行。

如果在ViewModelScope中出现了异常,应该选择就地捕获异常

src:https://developer.android.google.cn/kotlin/coroutines/coroutines-best-practices?hl=zh-cn


在协程中使用viewModelScope的方式 

https://medium.com/androiddevelopers/easy-coroutines-in-android-viewmodelscope-25bffb605471

Dipatcher:

协程中的Dispatchers.main Dispatchers.IO Dispatchers.default 这些会创建单例,还是每次调用都创建不同的实例?

Dispatchers.Main:

以上是Dispacthers.Main的构建过程。Dispatcher.Main在文档中的描述的特点是:该协程调度器被限定在了主线程中,可以和UI对象进行交互。


MainDispatcherLoader

MainDispatcherLoader类是一个object,也就是说这个类是一个天生的单例。MainDispatcherLoader通过loadMainDispatcher创建了dispatcher。

接下来调用了MainDispatcherFactory的方法创建Dispacther

。MainDispatcherFactory的实现类只有AndroidDispatcherFactory一个。在AndroidDispatcherFatctory的重写方法中,我们发现真正的返回对象是HandlerContext:


HandlerContext其中一个参数就是通过主线程的Looper构建的Handler实例。所以其实现在已经可以得出结论,每次调用Dispatchers.Main都会创建一个新的HandlerContext对象。我们通过这个Handler对象和主线程进行交互。特别是可以看看这里的dispatch方法:

其他的Dispatcher也是类似的,所以我们可以在Koin Module中使用factory模块生成Dispatcher的Service。


总结:

  1. 理解协程首先需要理解什么叫做结构性并发。结构性并发保证了所有的协程、挂起函数都能被CoroutineScope管理生命周期。

  2. 创建一个协程会继承CoroutineScope中的内容,但是如果指定了Dispatchers.Main或者其他的Dispatchers.IO 这里不存在【单例】或者是【复用】机制,会重新创建一个Dispacthers的实例。


Coroutine 学习(二)ViewModelScope LifeCycleScope Dispatcher的评论 (共 条)

分享到微博请遵守国家法律