關於Android LifecycleScope的一點點發現
例子
程式碼的執行順序應該是one()
,two()
還是two()
,one()
,或者是兩個呼叫的時機是隨機的,看協程的排程呢?相信很多人都會選擇最後一個.但實際無論執行多少次都是下面的結果
並且launch()
方法傳入的suspend 函式甚至會阻塞主執行緒,怎麼回事兒,這個協程是假的協程?嗎!
先說結論
Kotlin的協程在不同的平臺有不同的實現方式.本文以我最熟悉的Android平臺為例.在Android中,啟動一個協程使用Dispatcher.Main.immediate
作為排程器的話,如果當前執行緒是主執行緒,就會將任務立即在主執行緒執行,如果是在其它執行緒中,使用Handler.post()
方法分給主執行緒去執行.
如果是Dispatcher.Main
作為排程器,就會直接使用主執行緒的Handler.post()
去執行.
CoroutineDispatcher:協程排程器
在匯入了androidx.lifecycle:lifecycle-runtime-ktx
依賴後,可以在Activity中使用lifecycleScope.launch{}
啟動一個協程,這裡預設的上下文就是 EmptyCoroutineContext
,因此啟動的協程上下文就是
kotlin
lifecycleScope.coroutineContext+EmptyCoroutineContext
看下lifecycleScope
是怎麼來的
這樣lifecycleScope.launch{}
這樣啟動一個協程預設的排程器就是Dispatcher.Main.immediate
Dispatcher顧名思義就是排程器,在這裡就是負責協程的排程功能,匯入依賴檢視Android平臺的Disptcher.Main
的最終實現是由HandlerContext
實現的
HandlerContext
重寫了isDispatchNeeded
方法
檢視isDispatchNeeded
的註釋可知道如果該方法返回true就會通過dispatch()
將協程分發出去,false就會令協程在當前執行緒恢復,因此Disptcher.Main
會始終呼叫dispather()
來進行分發,而Dispatcher.Main.immediate
只有在非主執行緒中會呼叫dispatch()
.何時會呼叫CoroutineDispatcher.isDispatchNeeded()
方法呢?通過檢視函式呼叫在DispatchedContinuation.resumeWith()
方法中使用到了它.
DispatchedContinuation:協程排程的發起者
這裡只關注DispatchedContinuation
是如何讓協程立即在當前執行緒恢復的邏輯
executeUnconfined()
方法是DispatchedContinuation
的一個拓展函式,協程的執行是交給EventLoop處理,它類似Handler的MessageQueue,如果當前執行緒的佇列已滿就會使用EventLoop.dispatchUnconfined()
將這個協程排程到當前的EventLoop中,否則直接呼叫runUnconfinedEventLoop()
將協程執行