先决条件:
- Android上的Kotlin协程
- Kotlin协程中的挂起函数
众所周知,当用户在任何协程中调用delay()函数时,它不会阻塞正在运行它的线程,而调用delay()函数则可以执行其他一些操作,例如更新UI等事物。由于延迟函数是一个挂起函数,因此必须从协程或另一个挂起函数。
runBlocking()函数的定义
根据官方文档,可以将runBlocking()函数定义为:
runBlocking is a coroutine function. By not providing any context, it will get run on the main thread.Runs a new coroutine and blocks the current thread interruptible until its completion. This function should not be used from a coroutine. It is designed to bridge regular blocking code to libraries that are written in suspending style, to be used in main functions and in tests.
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。