Home > Software engineering >  What is the difference if I use "withContext(Dispatchers.IO)" or not?
What is the difference if I use "withContext(Dispatchers.IO)" or not?

Time:11-13

Hi, I am a beginner in coroutines but I have some problems ...

I have two different codes, the first use withContext(Dispatchers.IO) , and the second doesn't use it.

  1. what is the difference between these two codes?

  2. why are they have the same result?

  3. How does every code work line by line?

  4. Tips to learn everything in coroutines.


  • the first code

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        GlobalScope.launch(Dispatchers.IO) {
            print("aly")
            print("younes")
        }
    }

    suspend fun print(name:String) {
        withContext(Dispatchers.IO) {
            delay(2000)
            Log.d("younes3", name)
        }
    }

}

  • the second code

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        GlobalScope.launch(Dispatchers.IO) {
            print("aly")
            print("younes")
        }
    }

    suspend fun print(name:String) {
        delay(2000)
        Log.d("younes3", name)
    }
}
  • the first code

2022-11-13 10:28:02.122 21136-21176 younes3 com.example.coroutines1 D aly

2022-11-13 10:28:04.124 21136-21178 younes3 com.example.coroutines1 D younes

  • the second code

2022-11-13 10:28:26.511 21286-21326 younes3 com.example.coroutines1 D aly

2022-11-13 10:28:28.512 21286-21328 younes3 com.example.coroutines1 D younes

CodePudding user response:

Your question is pretty unfocused, so I'll focus on what Dispatchers.IO does and why your code works exactly the same with or without it.

As a general rule, we should not perform any blocking I/O operations when using coroutines. That means reading/writing files or network while using utilities like e.g. InputStream which is blocking. Blocking inside coroutines may greatly degrade the performance and responsiveness of the whole application using coroutines.

However, it would be very hard to never perform any blocking I/O. For this reason, Kotlin coroutines framework provided an utility that allows blocking I/O by executing it inside a very special context - this is Dispatchers.IO. Internally, it schedules the blocking operation to a special thread pool which was designed specifically for this purpose.

You don't see any difference between both code samples, because GlobalScope.launch(Dispatchers.IO) already run its code using Dispatchers.IO. print() is invoked using Dispatchers.IO already, so additional withContext(Dispatchers.IO) doesn't do anything.

I suggest switching to Dispatchers.IO only in the code that handles blocking I/O directly. We generally should not switch to this dispatcher if our code only invokes other suspending functions, even if these functions are somehow related to I/O operations. For this reason, you should not use Dispatchers.IO in GlobalScope.launch().

Additionally, print() function in your code also doesn't do any blocking I/O, so as a matter of fact, you should remove withContext() as well. If that was just an example and you are going to perform blocking I/O inside print(), then you should use withContext(Dispatchers.IO) there, but still not in onCreate().

  • Related