Bird
Raised Fist0
Android Kotlinmobile~20 mins

Exception handling in coroutines in Android Kotlin - Mini App: Build & Ship

Choose your learning style10 modes available
Build: Coroutine Exception Handler Demo
This screen demonstrates how to handle exceptions in Kotlin coroutines by showing success or error messages.
Target UI
-------------------------
| Coroutine Exception    |
| Handler Demo          |
|-----------------------|
| [Start Coroutine]     |
|                       |
| Message:              |
|                       |
|                       |
|-----------------------|
Add a Button labeled 'Start Coroutine' that triggers a coroutine
Inside the coroutine, simulate a task that throws an exception
Use CoroutineExceptionHandler to catch the exception
Display the exception message in the Message area below the button
If no exception, display 'Task completed successfully!'
Starter Code
Android Kotlin
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.launch

class MainActivity : ComponentActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
      MaterialTheme {
        Surface(modifier = Modifier.padding(16.dp)) {
          CoroutineExceptionDemo()
        }
      }
    }
  }
}

@Composable
fun CoroutineExceptionDemo() {
  var message by remember { mutableStateOf("") }
  val coroutineScope = rememberCoroutineScope()

  // TODO: Add CoroutineExceptionHandler here

  Column {
    Button(onClick = {
      // TODO: Launch coroutine with exception handling
    }) {
      Text("Start Coroutine")
    }

    Text(text = "Message: $message", modifier = Modifier.padding(top = 16.dp))
  }
}
Task 1
Task 2
Task 3
Task 4
Task 5
Solution
Android Kotlin
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class MainActivity : ComponentActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
      MaterialTheme {
        Surface(modifier = Modifier.padding(16.dp)) {
          CoroutineExceptionDemo()
        }
      }
    }
  }
}

@Composable
fun CoroutineExceptionDemo() {
  var message by remember { mutableStateOf("") }
  val coroutineScope = rememberCoroutineScope()

  val handler = CoroutineExceptionHandler { _, exception ->
    message = "Caught exception: ${exception.localizedMessage}"
  }

  Column {
    Button(onClick = {
      message = ""
      coroutineScope.launch(handler) {
        delay(500) // Simulate work
        throw Exception("Something went wrong!")
        // message = "Task completed successfully!" // This line won't run because of exception
      }
    }) {
      Text("Start Coroutine")
    }

    Text(text = "Message: $message", modifier = Modifier.padding(top = 16.dp))
  }
}

We create a CoroutineExceptionHandler that updates the message state when an exception occurs. The coroutine is launched with this handler, so if an exception is thrown inside, it is caught and the UI updates with the error message. This shows how to handle exceptions gracefully in coroutines and update the UI accordingly.

Final Result
Completed Screen
-------------------------
| Coroutine Exception    |
| Handler Demo          |
|-----------------------|
| [Start Coroutine]     |
|                       |
| Message:              |
| Caught exception:     |
| Something went wrong! |
|-----------------------|
User taps 'Start Coroutine' button
Coroutine starts and throws an exception after a short delay
Exception is caught by CoroutineExceptionHandler
Message area updates to show 'Caught exception: Something went wrong!'
Stretch Goal
Modify the coroutine to sometimes complete successfully and sometimes throw an exception randomly.
💡 Hint
Use kotlin.random.Random.nextBoolean() inside the coroutine to decide whether to throw or complete.

Practice

(1/5)
1. What is the primary purpose of using try-catch blocks inside Kotlin coroutines?
easy
A. To pause the coroutine execution
B. To start a new coroutine
C. To catch and handle exceptions that occur during coroutine execution
D. To cancel the coroutine immediately

Solution

  1. Step 1: Understand coroutine error handling

    Coroutines can throw exceptions during their execution which need to be handled to avoid app crashes.
  2. Step 2: Role of try-catch in coroutines

    Using try-catch inside a coroutine allows catching exceptions locally and handling them gracefully.
  3. Final Answer:

    To catch and handle exceptions that occur during coroutine execution -> Option C
  4. Quick Check:

    try-catch in coroutine = catch exceptions [OK]
Hint: try-catch inside coroutine catches errors locally [OK]
Common Mistakes:
  • Thinking try-catch starts or cancels coroutines
  • Confusing try-catch with coroutine builders
  • Assuming try-catch pauses coroutine
2. Which of the following is the correct syntax to define a CoroutineExceptionHandler in Kotlin?
easy
A. val handler = CoroutineExceptionHandler(context, exception) -> println(exception)
B. val handler = CoroutineExceptionHandler { context, exception -> println(exception) }
C. val handler = CoroutineExceptionHandler(context) { exception -> println(exception) }
D. val handler = CoroutineExceptionHandler { exception -> println(exception) }

Solution

  1. Step 1: Recall CoroutineExceptionHandler syntax

    The handler takes a lambda with two parameters: CoroutineContext and Throwable.
  2. Step 2: Match correct lambda parameters

    val handler = CoroutineExceptionHandler { context, exception -> println(exception) } correctly uses (context, exception) parameters and prints the exception.
  3. Final Answer:

    val handler = CoroutineExceptionHandler { context, exception -> println(exception) } -> Option B
  4. Quick Check:

    CoroutineExceptionHandler syntax = val handler = CoroutineExceptionHandler { context, exception -> println(exception) } [OK]
Hint: CoroutineExceptionHandler lambda needs context and exception [OK]
Common Mistakes:
  • Omitting context parameter in lambda
  • Using wrong lambda parameter order
  • Incorrect parentheses placement
3. What will be the output of this Kotlin coroutine code snippet?
val handler = CoroutineExceptionHandler { _, exception -> println("Caught: ${exception.message}") }

GlobalScope.launch(handler) {
  throw IllegalArgumentException("Invalid argument")
}
Thread.sleep(100)
medium
A. Caught: Invalid argument
B. No output, exception crashes app
C. Caught: null
D. Compilation error due to handler

Solution

  1. Step 1: Understand CoroutineExceptionHandler usage

    The handler catches uncaught exceptions in the coroutine and prints the message.
  2. Step 2: Analyze the thrown exception

    The coroutine throws IllegalArgumentException with message "Invalid argument", which the handler prints.
  3. Final Answer:

    Caught: Invalid argument -> Option A
  4. Quick Check:

    Exception caught and printed = Caught: Invalid argument [OK]
Hint: ExceptionHandler prints exception message on uncaught errors [OK]
Common Mistakes:
  • Assuming exception crashes app without handler
  • Expecting null message output
  • Confusing compile error with runtime behavior
4. Identify the error in this coroutine exception handling code:
val handler = CoroutineExceptionHandler { context, exception ->
  println("Error: ${exception.message}")
}

GlobalScope.launch {
  throw RuntimeException("Failure")
}
medium
A. GlobalScope.launch requires a try-catch block inside
B. CoroutineExceptionHandler lambda has wrong parameters
C. RuntimeException cannot be caught by CoroutineExceptionHandler
D. Handler is not attached to the coroutine, so exception is uncaught

Solution

  1. Step 1: Check handler usage

    The handler is defined but not passed to the coroutine builder, so it is unused.
  2. Step 2: Effect of missing handler attachment

    Without attaching handler to launch, exceptions are not caught by it and crash the app.
  3. Final Answer:

    Handler is not attached to the coroutine, so exception is uncaught -> Option D
  4. Quick Check:

    Handler must be passed to launch = Handler is not attached to the coroutine, so exception is uncaught [OK]
Hint: Attach handler to launch to catch exceptions [OK]
Common Mistakes:
  • Defining handler but forgetting to pass it to launch
  • Thinking all exceptions are caught automatically
  • Misunderstanding CoroutineExceptionHandler parameters
5. You want to handle exceptions globally for all coroutines in your app using CoroutineExceptionHandler. Which approach correctly applies this handler to multiple coroutines launched in different scopes?
hard
A. Create a single CoroutineExceptionHandler instance and pass it to each coroutine builder's context
B. Use try-catch inside each coroutine instead of CoroutineExceptionHandler
C. Attach CoroutineExceptionHandler only to the first coroutine launched
D. Use a global try-catch block outside all coroutine launches

Solution

  1. Step 1: Understand global exception handling

    CoroutineExceptionHandler can be reused by passing the same instance to multiple coroutine builders.
  2. Step 2: Evaluate options for applying handler globally

    Passing the handler to each coroutine context ensures all coroutines use the same global handler.
  3. Final Answer:

    Create a single CoroutineExceptionHandler instance and pass it to each coroutine builder's context -> Option A
  4. Quick Check:

    Reuse handler by passing to each coroutine = Create a single CoroutineExceptionHandler instance and pass it to each coroutine builder's context [OK]
Hint: Pass one handler instance to all coroutine contexts [OK]
Common Mistakes:
  • Using try-catch only inside coroutines misses global handling
  • Attaching handler to only one coroutine limits scope
  • Trying to catch exceptions outside coroutine scope
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard