DEV Community

Cover image for Coroutines, key Concepts
Jess Barrientos
Jess Barrientos

Posted on

Coroutines, key Concepts

Basically, a coroutine is a Thread... a lightweight one, you can run a bunch of coroutines without even notice. They help us to manages our async code and their syntax is simple and easy to understand.

//Basic Example
fun main () {
    GlobalScope.launch {
        delay(2000)
        println("Hello world")
    }
    Thread.sleep(3000)
}
Enter fullscreen mode Exit fullscreen mode

What is Scope?
Scope create, run, and stop Coroutines, also provides lifecycle methods.

  • GlobalScope.launch{}: the scope of these coroutines will be the entire application, so when the app stops the coroutine will stop.
  • runBlocking: it will run on the main thread. Runs a new coroutine and blocks the current thread interruptible until its completion.
  • CoroutineScope: it will create a new scope and will run until all the inner coroutines finish.

Examples:

fun main () {
  runBlocking {
     launch {
     println("runBlocking ")
     }
  }

  GlobalScope.launch {
     println("runBlocking")
  }

   coroutineScope {
      launch {
    println("runBlocking")
      }
  }
}
Enter fullscreen mode Exit fullscreen mode

What is Context?

It's a set of variables and data associated with the coroutines.

  • Dispatcher: Specify the thread in which our coroutine will run
  • Job: Handle the coroutine lifecycle.

What is a Suspending function?

It's a function that can be run in a Coroutine. So the only difference is that we need to add the 'suspended' key-word at the beginning.

suspend fun myFunction(){
    println("Hello, I'm suspended")
}
Enter fullscreen mode Exit fullscreen mode

What is a Job?

A job is the result of the '.launch()', so we can store this in a variable and use it. ( That way we can manipulate the lyfecycle of the corotutine).

   val job = GlobalScope.launch {
      // Coroutine work...
   }
Enter fullscreen mode Exit fullscreen mode

What is a Dispatcher?

Manage in which thread the coroutine will run. We can specify (if we want) in which thread our coroutine will run and switch between threads with the keyword: withContext

Common dispatchers:

launch(Dispatchers.Main) { // Main -- will work with main thread (UI)
    println("Main")
}
launch(Dispatchers.IO) { // IO -- will work with IO thread, network or file work
    println("IO")
}
launch(Dispatchers.Unconfined) { // not confined -- will work with main thread
    println("Unconfined")
}
launch(Dispatchers.Default) { // will get dispatched to DefaultDispatcher 
    println("Default")
}
Enter fullscreen mode Exit fullscreen mode

withContext :
Let us change the context of our coroutine.

fun main() { 
   runBlocking {
    launch(Dispatchers.Default){
        println(Default context)
        withContext(Dispatchers.IO){        
           println(IO context)
       }   
                println(Default context)
    }   
  }
}
Enter fullscreen mode Exit fullscreen mode

What is a Deferred?

A future result of a coroutine, for example, the result for an API call. So we need to wait for this value and we are going to use async.

fun main (){
  runBlocking {
     val myDefferred = async { suspendfun() }
  }
}

suspend fun suspendfun(): Int {
    delay(50000)
    return 10
}
Enter fullscreen mode Exit fullscreen mode

Top comments (3)

Collapse
 
andreidascalu profile image
Andrei Dascalu

I never quite understood lightweight threads. What makes it light compared to a regular thread?

Collapse
 
jbc7ag profile image
Jess Barrientos

Basically, every Thread has its own stack. According to the documentation, 64k is the least amount of stack space allowed per thread in the JVM while a simple coroutine in Kotlin occupies only a few dozen bytes of heap memory.

Try to run this example and see It on your own. Then, change it to "normal" Threads and see how your app crash ahah

fun main(){
    runBlocking {
        repeat(1_000_000){
            launch {
                print(".")
            }
        }
    }
} 
Enter fullscreen mode Exit fullscreen mode
Collapse
 
andreidascalu profile image
Andrei Dascalu

Every thread has a stack, that's the definition of a thread (well, that plus registers, counters and a couple other things). What makes this lightweight?