Cancellation is cooperative. A suspending network adapter may cancel correctly while a subsequent plain Kotlin loop has no suspension or cancellation check. Moving that loop to Default protects Main but does not make it stop automatically.
For independently parsed records, use a checkpoint between records:
suspend fun parseRecords(
records: List<String>,
cpuDispatcher: CoroutineDispatcher
): List<Record> = withContext(cpuDispatcher) {
buildList {
for (raw in records) {
ensureActive()
add(parseRecord(raw))
}
}
}
Record and parseRecord belong to the application. Supply an appropriate CPU dispatcher. The check bounds cancellation responsiveness only by the duration of one record's parsing. If one record takes seconds, break that work into smaller pieces or use a parser with cancellation support.
ensureActive() checks cancellation without yielding execution. yield() also gives other work an opportunity to run and checks cancellation. Choose checkpoints based on responsiveness and workload rather than inserting a suspension into every tiny arithmetic operation.
What should happen to partial results? Define whether they are discarded or deliberately published. Avoid committing a partial database replacement as if parsing completed successfully. Test cancellation mid-input and verify that resources close and existing data remains consistent.
Mark this when you can explain the answer in your own words.
Help fellow developers prepare for interviews
Sharing helps the Android community grow ๐