HOWTO · Kotlin

Kotlin runBlocking: 非コルーチンの世界をコルーチン コードで橋渡しする

Kotlin の runBlocking 関数を使用すると、スレッド全体をブロックできます。 この記事では、Kotlin コルーチン runBlocking について詳しく説明します。

このページの内容

Kotlin の runBlocking() 関数は、main スレッドをブロックするサスペンド関数です。 これは、同期コードと非同期コードの間のブリッジを作成するのに役立ちます。

この記事では、Kotlin runBlocking() とさまざまなシナリオでのその使用法について学びます。

Kotlin の runBlocking 関数

Kotlin の delay() 関数について聞いたことがあるかもしれません。 delay() 関数は、コルーチンを一時停止し、特定の時間遅らせます。

ただし、スレッド全体をブロックするわけではありません。 これは、delay() 関数を使用する場合でも、UI の変更などの他の操作を実行できることを意味します。

一方、runBlocking() 関数は、完了するまでスレッド全体をブロックします。 したがって、コンパイラは、runBlocking() コードを含むスレッドが完了するまで、他に何も実行しません。

Kotlin runBlocking() 関数によって起動された新しいスレッドは、main スレッドから起動されます。

これを理解するために、2つのコード例を見てみましょう。 最初のコードでは、GlobalScope.launch() で delay() 関数を使用します。 2 番目の例では、Kotlin の runBlocking() 関数で使用します。

GlobalScope.launch() で delay() を使用する

package com.example.mycoroutines

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class MainActivity : AppCompatActivity() {
    val TAG:String="This is Main Activity"
    override fun myFunc(savedInstanceState: Bundle?) {
        super.myFunc(savedInstanceState)
        setContentView(R.layout.activity_main)
        GlobalScope.launch(Dispatchers.Main) {
            delay(5000)
            Log.d(TAG,"Global Scope")
            Toast.makeText(applicationContext,"Thread executed in global scope",Toast.LENGTH_SHORT).show()
        }
        Log.d(TAG,"Not Global Scope")
        Toast.makeText(applicationContext,"Thread executed is not in Global Scope",Toast.LENGTH_SHORT).show()
    }
}

このようなコードを Android Studio で実行すると、タグ "Not Global Scope" が実行されます。 タグ "Global Scope" メッセージは、5 秒の遅延で実行されます。

これは、遅延があるだけであることを意味しますが、操作は引き続き実行されます。 したがって、スレッドは完全にはブロックされません。

Kotlin runBlocking() で delay() を使用する

前に見たように、GlobalScope.launch() で delay() 関数を使用すると、スレッド全体がブロックされません。

しかし、Kotlin runBlocking で使用すると、スレッドは runBlocking コードのすべての関数が実行されるまでブロックされます。 同じことを示す例を次に示します。

package com.example.mycoroutines

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class MainActivity : AppCompatActivity() {
    val TAG:String="This is Main Activity"
    override fun myFunc(savedInstanceState: Bundle?) {
        super.myFunc(savedInstanceState)
        setContentView(R.layout.activity_main)
        Log.d(TAG, "Prior using run blocking")
            runBlocking 
              {
              Log.d(TAG,"Entered run-blocking")
              delay(3000)

              Log.d(TAG,"Run-blocking started")
              Log.d(TAG,"Run-blocking ended")
            }
        Log.d(TAG,"Post using run blocking")
    }
}

このコードを使用すると、タグ "Post using run blocks" が最後に実行されます。 その理由は、runBlocking コード全体が実行されるまで、すべての実行が停止されるためです。