androidengineers.Book a session
โ† All interview questions
KotlinIntermediate4 min

How to manage series and parallel execution?

Answer

Start with the dependency graph. If loading exercises needs the course ID returned by another call, those operations are sequential. If the course summary and bookmarks are independent, they can overlap.

Example

The following application-specific calls are assumed to be main-safe suspending functions:

suspend fun loadCourse(id: String): CourseScreen = coroutineScope {
    val summary = async { repository.loadSummary(id) }
    val bookmarks = async { repository.loadBookmarks(id) }

    CourseScreen(summary.await(), bookmarks.await())
}

Start both children before awaiting either. Writing async { first() }.await() followed by async { second() }.await() still serializes those operations.

Failure and performance

The ordinary scope treats both results as required: a child failure cancels its sibling. If one result is optional, design a separate recovery policy. Avoid launching detached work just to make a screen appear faster; it creates unclear cancellation and error ownership.

Concurrency means overlapping lifetimes. On Main, independent suspending requests can overlap their waits without executing Kotlin code simultaneously. Actual CPU parallelism depends on the dispatcher and available threads. async alone does not move CPU work off Main.

Follow-up to practise

Does join() return a result or rethrow a target job's failure? No. It waits for completion. await() retrieves a Deferred's value or throws its failure. Parent cancellation can still make a caller's join() throw cancellation, so inspect the whole job hierarchy.

Reference

Android Developers: Coroutine best practices

Mark this when you can explain the answer in your own words.

Share & Help Others

Help fellow developers prepare for interviews

Sharing helps the Android community grow ๐Ÿ’š

Keep practising