Deep look into Coroutine Suspend Functions. Part 3. Get result from suspend function.
The series consists of 5 parts:
1. Suspend functions introduction
2. How does Continuation work
3. Get result from suspend function
4. How to create a suspend function
5. A small FAQ about suspend functions
In the previous part we discussed how suspend function is called from Continuation. Suspend function can return some value as a result of work. Let’s see how Continuation handles it.
In addition, I will add one more suspend function to show how switch
operator divides the code.
Let’s have a look at this code:
The download function returns file
that we use in the suspend function unzip.
In Continuation this code will be divided into the following three parts by the two suspend functions.
1) the download function and everything before it
2) the unzip function and everything between it and the download function
3) everything after the unzip function
The simplified Continuation code could look like this:
But it doesn’t work. Pay attention to passing the file from the download
to the unzip
function.
We are trying to get file
this way:
But download
is an asynchronous function. It starts to download file in the background thread and doesn’t return the file immediately as a result of the method call. Therefore, we cannot get file
like this. We need to use another way to pass the result of suspend function to Continuation.
As we discussed in the previous article, when the suspend function is done, it calls the method invokeSuspend
in Continuation. The suspend function passes the result of its work using this call. The method invokeSuspend
has an input parameter for this purpose.
Continuation knows that the suspend function download
passes the result here. Also, Continuation knows that label
is 1 at the moment of this call. Therefore, Continuation casts parameter result
to class File
in the switch branch case 1.
The function download
doesn’t return anything here. But when it’s done it will call invokeSuspend
and pass the result there. This result is casted to the File
class and used in the function unzip
.
Let’s do this example a bit more complicated and add the return value for unzip
. Now unzip
returns the size of the unzipped package.
Let’s show this value in the toast after unzip
is done:
Continuation code for this coroutine will be like this:
The mechanism is the same. When the function unzip
is done it will call invokeSuspend
and pass the result as Object
. In case 2 branch the result is casted to Long
and used in toast
.
Conclusion
The method invokeSuspend
calls suspend function, passes the Continuation and finishes current switch branch. When suspend function is done, it calls continuation.invokeSuspend
and passes the result of work. Next switch branch is called in invokeSuspend
. The result is casted to the needed type and used.