Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return value from coroutine scope

Is there a way to return value from a coroutine scope? for example like this:

suspend fun signUpUser(signUpData : SignUpUserRequest) : User {

CoroutineScope(Dispatchers.IO).launch() {

        val response = retrofitInstance.socialSignUP(signUpData)
        if (response.success) {
            obj = response.data
        } else {
                obj = response.message
        }
    }.invokeOnCompletion {
        obj = response.message
    }

    return obj
}

the problem is as soon as signupUser function called, return obj suspend statement run right away, not with response value.. its not running sequentially, what I expect is first response come and then function return obj but its not happening. why?

I tried run blocking, it served the purpose but is there better approach to do same task without run blocking? or is it alright?

Thanks in advance!

like image 208
blackHawk Avatar asked Jul 18 '20 07:07

blackHawk


People also ask

How do you return a value from coroutines?

Put a yield at the end of your coroutine with the value you want to return... Invoke it and get the return value using the utility class... public void Start()

How do I get a coroutine scope?

The easiest way to create a coroutine scope object is by using the CoroutineScope factory function 1. It creates a scope with provided context (and an additional Job for structured concurrency if no job is already part of the context).

What is the coroutine scope?

CoroutineScope() uses the context provided to it as a parameter for its coroutines and adds a Job if one is not provided as part of the context. MainScope() uses Dispatchers. Main for its coroutines and has a SupervisorJob.


2 Answers

If you need to run works in parallel then you can use coroutineScope or async coroutine builder functions. However, in your case you don't have more than a request and so it could be sequantial. As mentioned in previous answer you can use withContext. 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.

suspend fun getUser(signUpData: SignUpUserRequest): User = withContext(Dispatchers.IO) {
    // do your network request logic here and return the result
}

Please note that, when you are working with expression body with functions, always try to annotate return type explicitly.

EDIT

Coroutines use the regular Kotlin syntax for handling exceptions: try/catch or built-in helper functions like runCatching (which uses try/catch internally). Beware of that uncaught exceptions will always be thrown. However, different coroutines builders treat exceptions in different ways. It's always good to read official documentation or other sources (like this).

like image 168
Mirjalal Avatar answered Oct 05 '22 21:10

Mirjalal


You can use withContext function to run a code in background thread and return some result:

suspend fun signUpUser(signUpData : SignUpUserRequest): User = withContext(Dispatchers.IO) {    
    val response = retrofitInstance.socialSignUP(signUpData)
    if (response.success) response.data else response.message
}
like image 42
Sergey Avatar answered Oct 05 '22 20:10

Sergey