Androidがkotlinと結合してcorountineを使用する方法の例


最近Androidピットに入りましたが、まだ狂ったように勉強していますので、長い間ブログを書いていません。今日はコードの小さな断片を記録して、Androidでcorountineの小さい例を使います。
私自身は記帳ソフトを作って勉強していますので、gRPCを使いました。最初はスレッドを使ってネットワークの要求をしました。

thread {
 //       

 runOnUiThread {
  //   UI   
 }
}

今日はこのセットを全部書き直します。
まずcoroutineにはスケジューラがあります。英語では「Displatch」と言います。
  • Displatchers.Mainの中のcorountineはメインスレッド上に走っています。AndroidではUIスレッドとなりますので、この中のcorontineも大量の時間コードを実行すれば、カードUIの
  • になります。
  • Disppatch.IOは大IOを走る
  • です。
  • Disppatchers.Defaultは、CPU消費の高い
  • を実行するために使用されます。
  • Dispares.Uniconfinedは、任意の特定の実行スレッドにバインドされていません。
  • そして、複数のcorountineの間でグループ化できるように、プロセスに多くのスレッドを置くことができるように、またscopeという概念を作りました。デフォルトではグローバルscopeがあります。Global Scoopeといいます。全体的な変数と同じように、Androidでは、この中を走るCooutine、ライフサイクルはapと同じように長く、ここでcoroutineを始めることを勧めません。
    オススメの方式はActivityごとにscopeを作ってからlaunchを使います。
    だから私はこのように基類を書きます。
    
    abstract class BaseActivity : AppCompatActivity(), CoroutineScope {
     /*
        coroutine scope Main,   UI  (   )。    IO,      ,  
         launch(Dispatchers.IO) {}  ,       ,    launch(Dispatcher.Default) {}  
           launch。 UI     withContext(Dispatchers.Main) {}    
      */
     private val job = SupervisorJob()
     override val coroutineContext: CoroutineContext
      get() = Dispatchers.Main + job
    
     override fun onDestroy() {
      super.onDestroy()
      coroutineContext.cancelChildren()
     }
    
    
    このようにしてから、直接launchでcorountineができます。
    
    launch {
     val req = CreateFeedbackReq.newBuilder().build()
     val respAny = callRPC {
      api.createFeedback(req)
     }
     respAny?:return@launch
    
     val resp = respAny as CreateFeedbackResp
     if (handleRespAction(resp.action)) {
      withContext(Dispatchers.Main) {
       showSnackBar(R.string.thank_you_for_feedback)
       delay(1000)
       finish()
      }
     }
    }
    
    
    以上のように、デフォルトでは、root cooutiveは現在のactivityであり、彼らはDisptch.Mainでデフォルトで実行します。coroutineが他のdispatcherで実行するなら、withContextを使って、またUIを更新したいなら、withContextを使います。
    どうしてlaunchはパラメータを伝えないと直接使うDispactch.Mainですか?実はCoroutineScoopeはインターフェースです。coroutine Contectは中の変数です。
    
    public interface CoroutineScope {
     /**
      * The context of this scope.
      * Context is encapsulated by the scope and used for implementation of coroutine builders that are extensions on the scope.
      * Accessing this property in general code is not recommended for any purposes except accessing the [Job] instance for advanced usages.
      *
      * By convention, should contain an instance of a [job][Job] to enforce structured concurrency.
      */
     public val coroutineContext: CoroutineContext
    }
    
    launchの実現を見に来ました。
    
    public fun CoroutineScope.launch(
     context: CoroutineContext = EmptyCoroutineContext,
     start: CoroutineStart = CoroutineStart.DEFAULT,
     block: suspend CoroutineScope.() -> Unit
    ): Job {
     val newContext = newCoroutineContext(context)
     val coroutine = if (start.isLazy)
      LazyStandaloneCoroutine(newContext, block) else
      StandaloneCoroutine(newContext, active = true)
     coroutine.start(start, coroutine, block)
     return coroutine
    }
    
    @ExperimentalCoroutinesApi
    public actual fun CoroutineScope.newCoroutineContext(context: CoroutineContext): CoroutineContext {
     val combined = coroutineContext + context
     val debug = if (DEBUG) combined + CoroutineId(COROUTINE_ID.incrementAndGet()) else combined
     return if (combined !== Dispatchers.Default && combined[ContinuationInterceptor] == null)
      debug + Dispatchers.Default else debug
    }
    
    
    デフォルトでは、現在のcooutine Contectを前に置いています。
    Kotlinのcooutineはとても使いやすいです。でも、ちょっと複雑な感じがします。私もまだ勉強しています。
    ref:
    https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/index.html
    ここでは、AndroidとCotlinを結合したcorountineの記事を紹介します。AndroidとCotlinを結合してcoroutineの内容を使用しています。以前の文章を検索したり、下記の関連記事を見たりしてください。これからもよろしくお願いします。