Kotlin runBlocking: Bridging the Non-Coroutine World With Coroutine Code

The Kotlin runBlocking() function is a suspend function that blocks the main thread. It helps create a bridge between the synchronous and asynchronous code.

In this article, we will learn about Kotlin runBlocking() and its uses in different scenarios.

the runBlocking Function in Kotlin

You might have heard about the delay() function in Kotlin. The delay() function suspends the coroutine and delays it for a specific time.

However, it does not block the entire thread. It means that when we use the delay() function, we can still perform other operations like making changes in the UI.

On the other hand, the runBlocking() function blocks an entire thread until its completion. Hence, the compiler will not execute anything else until the thread with the runBlocking() code is completed.

The new thread launched by the Kotlin runBlocking() function is launched from the main thread.

To understand this, let’s look at two example codes. In the first code, we will use the delay() function in GlobalScope.launch(). And in the second example, we will use it in the Kotlin runBlocking() function.

Use delay() in GlobalScope.launch()

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()
    }
}

When you run such a code in the Android Studio, the tag "Not Global Scope" is executed. The tag "Global Scope" message is then executed with a delay of 5 seconds.

It means there is only a delay, but operations are still performed. Hence, the thread is not blocked completely.

Use delay() in Kotlin runBlocking()

As seen earlier, the entire thread is not blocked when we use the delay() function in the GlobalScope.launch().

But when we use it in Kotlin runBlocking, the thread is blocked until all the functions from the runBlocking code are executed. Here’s an example to demonstrate the same.

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")
    }
}

When we use this code, the tag "Post using run blocking" is executed last. The reason is that all the executions are stopped until the entire runBlocking code is executed.