What is suspend function in Kotlin Coroutines?

In this blog, we are going to learn about the suspend function in Kotlin Coroutines. Suspend function is the building block of the Coroutines in Kotlin. It is important to learn about the suspend function. We will deep dive into the source code of Kotlin to understand it today.

Let's get started.

The definition of suspend function:

Suspend function is a function that could be started, paused, and resume.

What exactly does it mean?

The below image tells more about it.

  • functionA was running.
  • functionA was suspended after some time.
  • While the functionA was suspended, functionB started running and finished its work.
  • Then again, functionA started running.

Now, the question is how does it work.

How does the suspend function work?

For that, we need to discuss a little about the Coroutines. If you are interested in mastering the Kotlin Coroutines, learn from here.

Coroutines = Co + Routines

Here, Co means cooperation and Routines means functions.
It means that when functions cooperate with each other, we call it as Coroutines.

Let's understand this with an example. I have written the below code in a different way just for the sake of understanding. Suppose we have two functions as functionA and functionB.

functionA as below:

fun functionA(case: Int) {
    when (case) {
        1 -> {
            taskA1()
            functionB(1)
        }
        2 -> {
            taskA2()
            functionB(2)
        }
        3 -> {
            taskA3()
            functionB(3)
        }
        4 -> {
            taskA4()
            functionB(4)
        }
    }
}

And functionB as below:

fun functionB(case: Int) {
    when (case) {
        1 -> {
            taskB1()
            functionA(2)
        }
        2 -> {
            taskB2()
            functionA(3)
        }
        3 -> {
            taskB3()
            functionA(4)
        }
        4 -> {
            taskB4()
        }
    }
}

Then, we can call the functionA as below:

functionA(1)

Here, functionA will do the taskA1 and give control to the functionB to execute the taskB1.

Then, functionB will do the taskB1 and give the control back to the functionA to execute the taskA2 and so on.

The important thing is that functionA and functionB are cooperating with each other.

It has given us the power: Execute a few lines of functionA and then execute a few lines of functionB and then again a few lines of functionA and so on.

With Kotlin Coroutines, the above cooperation can be done very easily which is without the use of when or switch case which I have used in the above example for the sake of understanding.

Here comes, the suspend keyword in the picture. When we add the suspend keyword in the function, all the cooperations are automatically done for us. We don't have to use when or switch case. When we write like below:

suspend fun doSomething(request: Request): Response {
     // do something
}

Internally, it gets converted by the compiler to another function without the suspend keyword with an extra parameter of the type Continuation<T> like below:

fun doSomething(request: Request, continuation: Continuation)...

The Continuation<T> is an interface which looks like below(taken from Kotlin source code):

public interface Continuation<in T> {
    public val context: CoroutineContext
    public fun resumeWith(result: Result<T>)
}

In addition to that, it has two extension functions.

fun <T> Continuation<T>.resume(value: T)
fun <T> Continuation<T>.resumeWithException(exception: Throwable)

If you notice the functions closely, they can be used to resume the coroutine with a return value or with an exception if an error had occurred while the function was suspended.

This way, a function could be started, paused, and resume with the help of Continuation. We just have to use the suspend keyword.

Note: Suspend functions are only allowed to be called from a coroutine or another suspend function. You can see that the async function which includes the keyword suspend. So, in order to use that, we need to make our function suspend too.

Let's take a very standard use-case of an Android Application which is as follows:

  • Fetch User from the server.
  • Show the User in the UI.
suspend fun fetchUser(): User {
    return withContext(Dispatchers.IO) {
        // make network call
        // return user
    }
}

fun showUser(user: User) {
    // show user
}

Note: If you are using the 3rd party networking library that makes the network call on background thread by default, in that case, no need to use withContext(Dispatchers.IO). We can skip that part to just write like below:

suspend fun fetchUser(): User {
     // make network call
     // return user
}

So, the suspend function fetchUser can only be called from another suspend function or a coroutine. We can't make the onCreate function of an activity suspend, so we need to call it from the coroutines like below:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    GlobalScope.launch(Dispatchers.Main) {
        val user = fetchUser() // fetch on IO thread
        showUser(user) // back on UI thread
    }
    
}

fetchUser will run on the IO thread for making the network call.

Only when the fetching of the user is completed, showUser will get called.

showUser will run on UI thread because we have used the Dispatchers.Main to launch it.

Now, we know what is suspend function, how does it work.

That's it for now.

If you are interested in mastering the Kotlin Coroutines, learn from here.

Show your love by sharing this blog with your fellow developers.

Click here to share on Twitter.

Also, Let’s become friends on Twitter, Linkedin, Github, Quora, and Facebook.