Blog Infos
Author
Published
Topics
,
Published
Definition (in context to programming):

  1. What are coroutines and how to create coroutines using coroutine builders in Kotlin?
  2. What aJob is and the different states a Jobcan be in?
Kotlin coroutines & structured concurrency
val parentJob = launch {
val childJob = launch {
var count = 1
while (count <= 5) {
println("Count: $count")
delay(100)
count++
}
}
}
delay(250)
println("Cancelling parent job")
parentJob.cancel()
-----------
OUTPUT:
Count: 1
Count: 2
Count: 3
Cancelling parent job
fun CoroutineScope.launch(
    context: CoroutineContext = EmptyCoroutineContext,
    // ...
): Job
Understanding cancellation
  • Whether the execution of code in a coroutine should continue or not after cancel() is invoked, is a decision that lies in the hands of a developer, which will, in turn, depend on the use case.
  • Execution of code within a coroutine even after cancel() is invoked does not mean that structured concurrency is violated since the parent Job will still wait for the children Job(s) to reach a final state before reaching its final state. A Job is in a final state when its isCompleted = true and we can use join() in our code to wait for the completion of a Job before executing any further code.
val parentJob = launch {
val childJob = launch {
var count = 1
val startTime = System.currentTimeMillis()
var nextPrintTime = startTime
while (count <= 5) {
if (System.currentTimeMillis() >= nextPrintTime) {
println("Count: $count")
nextPrintTime += 100L
count++
}
}
}
}
delay(250)
println("Cancelling parent job")
parentJob.cancel()
parentJob.join()
println("Parent job completed")
-----------
OUTPUT:
Count: 1
Count: 2
Count: 3
Cancelling parent job // cancels parentJob and hence, cancels childJob recursively
Count: 4 // childJob continues executing its code
Count: 5
Parent job completed // parentJob completes only after childJob. (Structured Concurrency)

Job Offers

Job Offers


    (Senior) Android Software Developer (w/m/d)

    Paradox Cat GmbH
    Munich
    • Full Time
    apply now

    Android Entwickler (m/w/d)

    CHECK24
    Augsburg, Berlin, Düsseldorf, Essen, Frankfurt, Leipzig, München und Münster
    • Full Time
    apply now

    Senior Software Engineer – OS

    Peloton
    New York, USA
    • Full Time
    apply now
Load more listings

OUR VIDEO RECOMMENDATION

, ,

Automated migration of Android apps to Bazel build system

Migrating large projects that consist of hundreds or thousands of modules and being maintained by a large team, from Gradle to Bazel might be challenging. I would like to discuss the process of automation of…
Watch Video

Automated migration of Android apps to Bazel build system

Pavlo Stavytskyi
Software Engineer
Lyft

Automated migration of Android apps to Bazel build system

Pavlo Stavytskyi
Software Engineer
Lyft

Automated migration of Android apps to Bazel build system

Pavlo Stavytskyi
Software Engineer
Lyft

Jobs

while (count <= 5 && isActive)
Parallel Decomposition
suspend fun performTasks(task1: String, task2: String) {
    val job1 = async { doTask(task1) }
    val job2 = async { doTask(task2) }
    mergeTasks(job1.await(), job2.await())
}
fun CoroutineScope.launch(
    // ...
    block: suspend CoroutineScope.() -> Unit
): Job
  • The Job can be directly written and executed within the lambda block of anotherJob, to implicitly use it as its scope. For instance:
val parentJob = launch {
    val childJob = launch { ... }
}
  • In a suspending function, you can wrap your code into a
    coroutineScope { … } block that establishes a boundary of your operation, its scope.
suspend fun performTasks(task1: String, task2: String) {
    coroutineScope {
        val job1 = async { doTask(task1) }
        val job2 = async { doTask(task2) }
        mergeTasks(job1.await(), job2.await())
    }
}
CoroutineContext vs CoroutineScope

This sounds confusing, doesn’t it? Let’s simplify this by defining CoroutineContext and CoroutineScope.

 

fun CoroutineScope.launch(
    context: CoroutineContext = EmptyCoroutineContext,
    // ...
): Job

CoroutineScope: It is just a wrapper around the context, that is, it is an interface that consists of a sole property — val coroutineContext: CoroutineContext. It has nothing else but context.

public interface CoroutineScope {
    public val coroutineContext: CoroutineContext
}
val parallelJob = launch {
delay(1000)
}
val parentJob = launch {
val childJob = launch(parallelJob) { // Notice how the context is explicitly provided
var count = 1
while (count <= 5) {
println("Count: $count")
delay(100)
count++
}
}
}
delay(250)
println("Cancelling parent job")
parentJob.cancel()
parentJob.join()
println("Parent job completed")
-----------
OUTPUT:
Count: 1
Count: 2
Count: 3
Cancelling parent job
Parent job completed
Count: 4
Count: 5 // childJob continues after parentJob (CoroutineScope),
// and is bound to parallelJob (CoroutineContext)

💡If you’re curious and wish to dive deeper into CoroutineContext and CoroutineScope, here’s a great blog.

 

YOU MAY BE INTERESTED IN

YOU MAY BE INTERESTED IN

blog
It’s one of the common UX across apps to provide swipe to dismiss so…
READ MORE
blog
Hi, today I come to you with a quick tip on how to update…
READ MORE
blog
Automation is a key point of Software Testing once it make possible to reproduce…
READ MORE
blog
Drag and Drop reordering in Recyclerview can be achieved with ItemTouchHelper (checkout implementation reference).…
READ MORE

Leave a Reply

Your email address will not be published.

Fill out this field
Fill out this field
Please enter a valid email address.

Menu