Sobes.tech
Middle

Tell in detail about coroutines in Kotlin.

sobes.tech AI

Answer from AI

Coroutines are lightweight threads managed by the framework, not the operating system. They allow writing asynchronous code in an imperative style, avoiding callback issues and improving readability.

Main components of coroutines:

  • CoroutineScope: Defines the scope of coroutines and binds them to the lifecycle. Provides methods to launch new coroutines (launch, async).
  • Job: Represents a running coroutine. Allows managing its lifecycle (cancel, wait for completion).
  • CoroutineContext: Configures coroutine behavior. Consists of elements:
    • CoroutineDispatcher: Determines the thread on which the coroutine will run.
    • Job: Manages the lifecycle.
    • CoroutineName: Name of the coroutine for debugging.
    • CoroutineExceptionHandler: Handles unhandled exceptions.
  • Suspend functions: Functions that can suspend their execution without blocking the thread and resume later. Marked with the suspend keyword.

Example usage:

import kotlinx.coroutines.*

fun main() = runBlocking { // Blocks the thread until all coroutines in this scope complete
    launch { // Launches a new coroutine in the current CoroutineScope
        delay(1000L) // Non-blocking delay for 1 second
        println("Hello!")
    }
    println("Hi,")
}

Dispatchers:

  • Dispatchers.Default: For CPU-intensive tasks.
  • Dispatchers.IO: For blocking I/O operations (network, disk).
  • Dispatchers.Main: For updating UI on the main thread (available in Android).
  • Dispatchers.Unconfined: Starts the coroutine immediately, but resumes in the thread where the suspend function finished.

Example of changing dispatcher:

import kotlinx.coroutines.*

fun main() = runBlocking {
    launch(Dispatchers.IO) {
        // Perform blocking I/O operation
    }
    withContext(Dispatchers.Main) {
        // Update UI
    }
}

async and await for getting results:

import kotlinx.coroutines.*

suspend fun doSomethingUsefulOne(): Int {
    delay(1000L)
    return 13
}

suspend fun doSomethingUsefulTwo(): Int {
    delay(1000L)
    return 29
}

fun main() = runBlocking {
    val one = async { doSomethingUsefulOne() } // Launches a coroutine and returns a Deferred<T>
    val two = async { doSomethingUsefulTwo() }

    // Wait for both asynchronous operations to complete and get their results
    println("Result: ${one.await() + two.await()}")
}

Exception handling:

import kotlinx.coroutines.*
import java.lang.ArithmeticException

fun main() = runBlocking {
    val handler = CoroutineExceptionHandler { _, exception ->
        println("Caught exception: $exception")
    }

    val job = GlobalScope.launch(handler) {
        throw ArithmeticException("Division by zero")
    }
    job.join() // Wait for coroutine completion for demonstration
}

Coroutines greatly simplify asynchronous programming in Android, providing a safe and readable way to manage background operations and UI updates.

Tell in detail about coroutines in Kotlin. — Android - sobes.tech