0
0
Android-kotlinHow-ToBeginner ยท 4 min read

How to Use Coroutines in Android for Asynchronous Tasks

In Android, you use coroutines by launching them within a CoroutineScope such as lifecycleScope or viewModelScope. Coroutines let you run long tasks like network calls without blocking the main thread, using launch or async builders inside suspend functions.
๐Ÿ“

Syntax

Coroutines run inside a CoroutineScope. You start a coroutine with launch for jobs that don't return a result, or async for jobs that return a value. Use suspend functions to mark code that can pause without blocking the thread.

  • CoroutineScope.launch { ... }: Starts a coroutine for background work.
  • suspend fun: Defines a function that can suspend.
  • withContext(Dispatchers.IO) { ... }: Switches to a background thread for heavy tasks.
kotlin
import kotlinx.coroutines.*

fun example() {
  CoroutineScope(Dispatchers.Main).launch {
    val result = doWork()
    println(result)
  }
}

suspend fun doWork(): String {
  return withContext(Dispatchers.IO) {
    // simulate long task
    "Work done"
  }
}
Output
Work done
๐Ÿ’ป

Example

This example shows how to use lifecycleScope in an Android Activity to run a coroutine that simulates a network call without blocking the UI thread.

kotlin
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

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

    lifecycleScope.launch {
      val data = fetchData()
      println(data) // Prints "Data loaded"
    }
  }

  private suspend fun fetchData(): String {
    return withContext(Dispatchers.IO) {
      delay(1000) // simulate network delay
      "Data loaded"
    }
  }
}
Output
Data loaded
โš ๏ธ

Common Pitfalls

Common mistakes when using coroutines in Android include:

  • Launching coroutines without a proper CoroutineScope, which can cause memory leaks.
  • Blocking the main thread by calling runBlocking or heavy work directly on the UI thread.
  • Not handling coroutine cancellation properly, leading to wasted resources.

Always use lifecycle-aware scopes like lifecycleScope or viewModelScope to avoid leaks.

kotlin
/* Wrong: launching coroutine without scope */
fun wrong() {
  GlobalScope.launch {
    // risky: no lifecycle awareness
  }
}

/* Right: use lifecycleScope in Activity or Fragment */
fun right(lifecycleScope: CoroutineScope) {
  lifecycleScope.launch {
    // safe: cancels with lifecycle
  }
}
๐Ÿ“Š

Quick Reference

Here is a quick summary of key coroutine components in Android:

ConceptDescription
CoroutineScopeDefines the lifecycle of coroutines, e.g., lifecycleScope, viewModelScope
launchStarts a coroutine that does not return a result
asyncStarts a coroutine that returns a result with Deferred
suspend functionFunction that can suspend without blocking a thread
Dispatchers.MainRuns coroutine on the main (UI) thread
Dispatchers.IORuns coroutine on a background thread for IO tasks
withContextSwitches coroutine context to another dispatcher
โœ…

Key Takeaways

Use lifecycle-aware CoroutineScopes like lifecycleScope to avoid memory leaks.
Mark long-running functions as suspend and call them inside coroutines.
Use Dispatchers.IO for background tasks to keep the UI responsive.
Avoid blocking the main thread by never running heavy work directly on it.
Handle coroutine cancellation properly to free resources when not needed.