Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin coroutines, is there a better way to return this value?

Struggling with coroutines, but is there a better way to use/get the value for a long running call out here before passing it onto another network coroutine with the callback? I've seen others but than i can't seem to use the value with the latest droid coroutine release, like I can't seem make this work Kotlin Coroutines with returning value

private suspend fun launchGeneratePayload(): String? { 
    return withContext (Dispatchers.Default) {
        try {
            val payloadString = slowStringGeneration()//Slow
            return@withContext payloadString
        } catch (e: java.lang.Exception) {
            return@withContext null
        }
    }
}

Where the value is ultimately used

public someFunction(callback: CallBack) {      
    val params: JSONObject = JSONObject()
    params.put("param1", "param1Value")
    runBlocking{ //probably should be launch or similar
        val payload = launchGeneratePayload()
        params.put("param2", payload)
        //call network function with params & callback
        //networkCall (
    } 
}

Thanks for any help

edit: I think was actually looking for was just a bit different with

suspend fun launchGeneratePayload(): String? =
    withContext(Dispatchers.Default) {
        try {
            slowStringGeneration() //slow
        } catch (e: java.lang.Exception) {
             null
        }
    }
}

Will add as an answer later incase i'm still off on this/else.

like image 295
Wesley Hunt Avatar asked Feb 28 '19 16:02

Wesley Hunt


People also ask

How do I return a value from coroutine?

Here is the small explaination from docs: Calls the specified suspending block with a given coroutine context, suspends until it completes, and returns the result. Please note that, when you are working with expression body with functions, always try to annotate return type explicitly.

Are coroutines better than threads?

The advantages of coroutines over threads are that they may be used in a hard-realtime context (switching between coroutines need not involve any system calls or any blocking calls whatsoever), there is no need for synchronization primitives such as mutexes, semaphores, etc.

When should I use GlobalScope coroutines?

Quoting definition of Global Scope from Kotlin's documentation– “Global scope is used to launch top-level coroutines which are operating on the whole application lifetime and are not cancelled prematurely.” GlobalScope creates global coroutines and these coroutines are not children of some specific scope.

What are Kotlin coroutines good for?

Coroutines were added to Kotlin in version 1.3 and are based on established concepts from other languages. On Android, coroutines help to manage long-running tasks that might otherwise block the main thread and cause your app to become unresponsive.


Video Answer


1 Answers

You can use launch coroutine builder to start the coroutine:

private var job: Job = Job()
private var scope = CoroutineScope(Dispatchers.Main + job)

fun someFunction(callback: CallBack) {
    val params: JSONObject = JSONObject()
    params.put("param1", "param1Value")
    scope.launch { // launch the coroutine
        val payload = generatePayload() // generate String without blocking the main thread
        params.put("param2", payload)
        //call network function with params & callback
        //networkCall (params, callback)
    }
}

suspend fun generatePayload(): String? = withContext(Dispatchers.Default) {
    try {
        slowStringGeneration() //slow
    } catch (e: java.lang.Exception) {
        null
    } 
}

Note: you can also make networkCall() as suspend, then you won't need to use callback.

To use Dispatchers.Main in Android add dependency to the app's build.gradle file

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1'

like image 62
Sergey Avatar answered Sep 28 '22 19:09

Sergey