When I'm running the code below in Android, it runs fine.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
runBlocking {
launch {
Log.d("Track", "main runBlocking pre : ${Thread.currentThread().name}")
delay(500)
Log.d("Track", "main runBlocking post : ${Thread.currentThread().name}")
}
}
}
It print
Track: main runBlocking pre : main
Track: main runBlocking post : main
However, if I provide the Main context to runBlocking
, as I have below
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
runBlocking(Dispatchers.Main) { // Provide Dispatchers.Main
launch {
Log.d("Track", "main runBlocking pre : ${Thread.currentThread().name}")
delay(500)
Log.d("Track", "main runBlocking post : ${Thread.currentThread().name}")
}
}
}
it hangs and not running it.
Note: the Dispatchers.Main
is using
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1'
Why did it hang?
I thought not providing Dispatchers.Main
to the runBlocking
is to have it run in main thread, which is the same as providing Dispatchers.Main
. Did I mis-understand it?
Note: The libraries I use are as below
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.4.21"
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1'
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.2'
runBlocking
's default dispatcher is a custom dispatcher that uses the thread it was called on to run the continuations of the coroutine. This is why when you log from within the runBlocking
coroutine block, it reports that it is on the main thread.
However, this is different that running something on Dispatchers.Main.
Dispatchers.Main
literally handles coroutine continuations by posting code blocks as runnables to the main Handler. However, that handler is currently running this onCreate
method, and won't be able to handle other messages in its queue until onCreate
returns. But runBlocking
won't return until its child coroutines return, so onCreate
can never return.
The default runBlocking
dispatcher on the other hand runs the continuations directly on the current thread before it even returns. It doesn't even know about Handlers. If you launch a coroutine into Dispatchers.main
from within runBlocking
with its default dispatcher, I think you'll have the same kind of hang.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With