📜  Kotlin协程中的runBlocking示例

📅  最后修改于: 2021-05-13 16:40:11             🧑  作者: Mango

先决条件:

  • Android上的Kotlin协程
  • Kotlin协程中的挂起函数

众所周知,当用户在任何协程中调用delay()函数时,它不会阻塞正在运行它的线程,而调用delay()函数则可以执行其他一些操作,例如更新UI等事物。由于延迟函数是一个挂起函数,因此必须从协程或另一个挂起函数。

runBlocking()函数的定义

根据官方文档,可以将runBlocking()函数定义为:

Kotlin
// smaple program in android studio to demonstrate coroutines
package com.example.gfgcoroutines
  
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="Main Activity"
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        GlobalScope.launch(Dispatchers.Main) {
            delay(3000)
            Log.d(TAG,"User is in the Global Scope ")
            Toast.makeText(applicationContext,"User is in the Global Scope ",Toast.LENGTH_SHORT).show()
        }
        Log.d(TAG,"User is not in the Global Scope ")
        Toast.makeText(applicationContext,"User is not in the Global Scope ",Toast.LENGTH_SHORT).show()
    }
}


Kotlin
package com.example.gfgcoroutines
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="Main Activity"
    override fun onCreate(savedInstanceState: Bundle?) 
    {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
          
        Log.d(TAG,"Before run-blocking")
            runBlocking 
              {
              Log.d(TAG,"just entered into the runBlocking ")
              delay(5000)
  
              Log.d(TAG,"start of the run-blocking")
              Log.d(TAG,"End of the runBlocking")
            }
        Log.d(TAG,"after the run blocking")
    }
}


Kotlin
package com.example.gfgcoroutines
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="Main Activity"
    override fun onCreate(savedInstanceState: Bundle?) 
    {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
          
        Log.d(TAG,"Before run-blocking")
             runBlocking 
               {
              Log.d(TAG,"just entered into the runBlocking ")
              delay(5000)
              launch(Dispatchers.IO)
             {
                delay(3000L)
                Log.d(TAG,"Finished to coroutine 1")
             }
  
             launch(Dispatchers.IO)
             {
                delay(3000L)
                Log.d(TAG,"Finished to coroutine 2")
             }
              Log.d(TAG,"start of the run-blocking")
              Log.d(TAG,"End of the runBlocking")
             }
         Log.d(TAG,"after the run blocking")
         GlobalScope.launch 
         {
            Log.d(TAG,"Logging in the globalScope")
         }
    }
}


日志输出:

上面程序的日志输出(以秒为单位的时间戳在图像中由椭圆环显示)

日志输出

从日志输出中可以看到,在“用户不在全局范围内”的日志之后,将打印“用户位于全局范围内”,这表明GlobalScope启动了协程,这不会阻塞主程序。线程,其他操作可以在延迟时间结束后执行。但是,当有人只想调用suspend函数而不需要协程行为时,可以从runBlocking调用suspend函数。因此,当您想调用诸如delay()之类的任何挂起函数并且不关心异步特性时,可以使用runBlocking函数。从runBlocking {(例如延迟())}GlobalScope.launch {的调用暂停函数}并调用暂停函数之间的区别是,将runBlocking阻塞主线程或在其使用和螺纹GlobalScope.launch {}不会阻塞主线程,在这种情况下,可以在线程延迟时执行UI操作。

runBlocking的另一个用例是用于JUnit的,其中一个需要访问来自测试函数中的暂停函数的测试。一个案例还使用runBlocking来深入了解协程,以弄清它们在幕后如何工作。让我们从下面的示例中查看runBlocking的实际工作方式:

科特林

package com.example.gfgcoroutines
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="Main Activity"
    override fun onCreate(savedInstanceState: Bundle?) 
    {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
          
        Log.d(TAG,"Before run-blocking")
            runBlocking 
              {
              Log.d(TAG,"just entered into the runBlocking ")
              delay(5000)
  
              Log.d(TAG,"start of the run-blocking")
              Log.d(TAG,"End of the runBlocking")
            }
        Log.d(TAG,"after the run blocking")
    }
}

日志输出:

上面程序的日志输出(以秒为单位的时间戳在图像中由椭圆环显示)

日志输出

上面的日志输出中的圆形椭圆圆圈显示了打印日志输出的时间戳。可以清楚地看到,“刚进入runBlocking”会遇到5秒钟的延迟,因此无法执行其他操作,必须等待5秒钟。同样在runBlocking函数外部的“运行阻塞之后”的Log语句也必须等待整个runBlocking函数完成其工作。让我们再举一个例子,尝试了解runBlocking的工作原理以及如何在其中启动不同的协程。

科特林

package com.example.gfgcoroutines
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="Main Activity"
    override fun onCreate(savedInstanceState: Bundle?) 
    {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
          
        Log.d(TAG,"Before run-blocking")
             runBlocking 
               {
              Log.d(TAG,"just entered into the runBlocking ")
              delay(5000)
              launch(Dispatchers.IO)
             {
                delay(3000L)
                Log.d(TAG,"Finished to coroutine 1")
             }
  
             launch(Dispatchers.IO)
             {
                delay(3000L)
                Log.d(TAG,"Finished to coroutine 2")
             }
              Log.d(TAG,"start of the run-blocking")
              Log.d(TAG,"End of the runBlocking")
             }
         Log.d(TAG,"after the run blocking")
         GlobalScope.launch 
         {
            Log.d(TAG,"Logging in the globalScope")
         }
    }
}

日志输出:

上面程序的日志输出(以秒为单位的时间戳在图像中由椭圆环显示)

日志输出

从上面的日志输出中可以看出,在延迟runBlocking之后,GlobalScope和launch都将执行。由于在带有启动函数的runBlocking中启动的两个协程都将在同一线程中执行,因此似乎两个协程都在并行运行,但是由于这两个协程都在同一线程中运行,所以这是不可能的,但是它们都在同一线程中运行。异步方式。因此可以说,仅当用户想要执行JUnit测试或仅调用暂停函数时,用户才应使用协程runBlocking。

想要一个节奏更快,更具竞争性的环境来学习Android的基础知识吗?
单击此处,前往由我们的专家精心策划的指南,以使您立即做好行业准备!