Skip to content

suspend function in Coroutine Kotlin

Published: at 6 min read

Table of content

Suspend function — explanation

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import retrofit2.Retrofit
import retrofit2.create

class WorkRepository {

    private val retrofit = Retrofit.Builder()
        .baseUrl("https://api.example.com")
        .build()

    private val apiService = retrofit.create(ApiService::class.java)

    suspend fun fetchData(): ResultType {
        return withContext(Dispatchers.IO) {
            try {
                val result = apiService.getData()
                // Process the result if needed
                result
            } catch (e: Exception) {
                // Handle errors or throw a custom exception
                throw CustomException("Failed to fetch data", e)
            }
        }
    }
}

In this above code snippet

class MainViewModel : ViewModel() {
    private val workRepository = WorkRepository()

    fun fetchData() {
        viewModelScope.launch {
            try {
                val result = myRepository.fetchData()
                // Update UI with the result
            } catch (e: CustomException) {
                // Handle custom exception
            } catch (e: Exception) {
                // Handle other exceptions
            }
        }
    }
}

Using suspend functions with coroutines simplifies asynchronous programming.

Threads Vs Coroutines in short

So first we see about Threads

  1. Concurrency Model: Threads provide a lower-level concurrency model, allowing to run multiple tasks concurrently.They are part of the Java language and can be used in Android for parallel execution.

  2. Complexity: Working with threads can be complex due to the need for synchronization, handling race conditions, and managing thread pools. Incorrect usage can lead to issues such as deadlocks and data corruption.

  3. Blocking Operations: Threads are suitable for blocking operations, such as network requests or disk I/O, without freezing the UI.

Thread {
    // Code to run in the background
    // ...
}.start()

Now going to the Coroutines

  1. Concurrency Model: Coroutines provide a higher-level concurrency model and are part of Kotlin. They are designed to simplify asynchronous programming, making code more readable and maintainable.

  2. Simplicity: Coroutines are simpler to use and manage compared to threads. They allow to write asynchronous code in a more sequential manner.

  3. Cancellation: Coroutines come with built-in support for cancellation, making it easier to handle the lifecycle of asynchronous tasks.

  4. Coroutines are non-blocking by nature, enabling to write asynchronous code without resorting to callbacks or complex threading constructs.

// Suspend function
suspend fun doBackgroundTask() {
    // Code to run in the background
    // ...
}

// Calling the suspend function from a coroutine
CoroutineScope(Dispatchers.Main).launch {
    doBackgroundTask()
}

Blocking Vs Suspending

Blocking Threads

fun main() {
    println("main function starts")
    threadRoutine(1, 500)
    threadRoutine(2, 300)
    Thread.sleep(1000)
    println("main function ends")
}

fun threadRoutine(number: Int, delay: Long) {
    thread{
        println("Routine $number starts working")
        Thread.sleep(delay)
        println("Routine $number has finished")
    }
}

In the above code snippet the main function calls the function called thread routine two times. For each invocation, a new thread is started in which work gets performed. This work is represented by a call to Thread.sleep. The main function sleeps for 1000 milliseconds to wait for the threads to complete.

Pictorial diagram of working of Blocking Thread blocking

Suspending a Coroutine

fun main() = runBlocking {
    println("main function starts")
    joinAll{
        async{suspendingCoroutine(1, 500)}.
        async{suspendingCoroutine(2,300)}
        async{
            repeat(5){
                println("other task is working on ${Thread.currentThread().name}")
                delay(100)
            }
        }
    }
    println("main function ends")
}

suspend fun suspendingCoroutine(number: Int, delay: Long) {
    println("Coroutine $number starts work on ${Thread.currentThread().name}")
    delay(delay)
    println("Coroutine $number has finished on ${Thread.currentThread().name}")
}

Output will look like of the above code snippet suspendOutput

Pictorial diagram of working of Suspend function suspending

In modern Android development, coroutines are commonly used to handle asynchronous tasks due to their simplicity, readability, and ability to manage concurrency efficiently. They provide an alternative to traditional thread-based approaches, promoting more scalable and maintainable code.

How delay() works

import kotlinx.coroutines.*

fun main() = runBlocking {
    println("Starts function")

    launch {
        println("Coroutine started")
        delay(3000) // Pause the coroutine for 3 seconds
        println("Coroutine resumed after delay")
    }

    println("End function")
}

In this example, the launch coroutine starts a new coroutine that prints messages before and after the delay(3000) statement. The delay() function causes the coroutine to pause for 3 seconds, allowing other tasks or coroutines to run in the meantime. The output will demonstrate the non-blocking nature of the delay() function.

Happy learning !

Share :
Written by:Parita Dey

Interested in Writing Blogs, showcase yourself ?

If you're passionate about technology and have insights to share, we'd love to hear from you! Fill out the form below to express your interest in writing technical blogs for us.

If you notice any issues in this blog post or have suggestions, please contact the author directly or send an email to hi@asdevs.dev.