Coroutines are how modern Android does asynchronous work. They replace callbacks and AsyncTask with sequential-looking code that is still non-blocking, and structured concurrency ties background work to a lifecycle so it cancels automatically. This is essential knowledge for any native Android code, including React Native native modules.

Key takeaways

  • Structured concurrency scopes coroutines to a lifecycle so they cancel cleanly.
  • Dispatchers move work between main, IO, and CPU threads explicitly.
  • Flow models streams of async values for reactive UI and data.

Structured concurrency

A coroutine runs inside a scope — viewModelScope, lifecycleScope, or a custom one. When the scope is cancelled (the screen closes), its coroutines cancel too, which prevents the leaks that plagued manual threading. suspend functions can call other suspend functions and suspend without blocking the thread.

Dispatchers and threading

Dispatchers decide which thread a coroutine uses: Main for UI, IO for network and disk, Default for CPU-bound work. withContext lets you switch dispatchers for a block, so you do a network call on IO and update state on Main without manual handlers.

Flow for streams

When you need a stream of values over time — location updates, database changes, sensor data — Flow models it with the same structured-concurrency guarantees. It pairs naturally with DataStore and Room, both of which expose Flows you can collect in the UI.