11

I would like to ask if it's possible to 'return' a value from a function if the function doing AsyncTask?

For example :

fun readData() : Int{
    val num = 1;
    doAsync { 
    for (item in 1..1000000){
        num += 1;
    }
    }
    return num;
}

The problem in this function is that the AsyncTask is not finish yet so i get a wrong value from the function ,any idea how to solve it?

is using a interface is the only why or there is a compilation handler like in Swift ?

omer tamir
  • 314
  • 1
  • 3
  • 11
  • There is no way to return a value in that sense. You could use a callback function. – fjc Aug 17 '17 at 08:04

4 Answers4

22

If you perform some calculation asynchronously, you cannot directly return the value, since you don't know if the calculation is finished yet. You could wait it to be finished, but that would make the function synchronous again. Instead, you should work with callbacks:

fun readData(callback: (Int) -> Unit) {
    val num = 1
    doAsync { 
        for (item in 1..1000000){
            num += 1
        }
        callback(num)
    }
}

And at callsite:

readData { num -> [do something with num here] }

You could also give Kotlin coroutines a try, which make async code look like regular synchronous code, but those may be a little complex for beginners. (By the way, you don't need semicolons in Kotlin.)

DarkCygnus
  • 7,420
  • 4
  • 36
  • 59
Christian Brüggemann
  • 2,152
  • 17
  • 23
  • 1
    I think you missed the parentheses surrounding the callback parameter Int: `fun readData(callback: (Int) -> Unit)`, otherwise Android Studio gives warning error (editing) – DarkCygnus Jun 14 '18 at 22:07
1

Not only in kotlin, this is not possible in any programming language to return from a async method. But what you can do is :

  1. Use co-routines like Christian suggested.
  2. Use Reactive approach like RxJava or RxKotlin and deal with stream of data where even though you can not return from your method in different thread, you can observe return type of the function from different thread.
  3. If you are doing very simple things, Callbacks can be helpful.
erluxman
  • 18,155
  • 20
  • 92
  • 126
0

Kotlin's co-routines are definitely your best bet. I've never actually tried but using a co-routine within an async task allows you return a value from within the task from the co-routine. I'll try coming up with a block of code to demonstrate that

0

just do it like this instead:

fun readData() : Int{
    val num = 1;
    for (item in 1..1000000){
        num += 1;
    }
return num

}


val scope = CoroutineScope(Dispatchers.Main)

scope.launch{
async(Dispatchers.IO){
readData()
}.await()

}

by the an alternative to async block using a context like this also should work:

fun readData() : Int{
    val num = 1;
    for (item in 1..1000000){
        num += 1;
    }
return num

}

 val scope = CoroutineScope(Dispatchers.Main)
     scope.launch {
                    withContext(Dispatchers.IO) { readData() }

then somewhere else create a courtine to run this thing async:

j2emanue
  • 60,549
  • 65
  • 286
  • 456