0

I have a function which returns a List of Strings. This function requesting a response from the server. But firstly the function returns null, then a bit later returns a response with String. How to make it return the string from the beginning, avoid "empty response"?

 var array = listOf<String>()

    private fun getNetworkResponse(): List<String> {

        scope.launch {
            val list = api.getVideo().data
            val reply = list?.map { it?.url }
            array = reply as List<String>
            Log.d(MY_TAG, "array 1 $array ")
        }

        Log.d(MY_TAG, "array 2 $array ")
        return array
    }

So above function first return empty array, and late with response:

Log array 2 []

Log array 1 [https://..]

2 Answers2

1

I found the solution: I use async suspend courutin. This function waits until the end of the task and returns the result.

suspend fun getNetworkResponse(): Array<String?> {
     scope.async {
                    ...
                    value = reply.toTypedArray()
                    Log.d(MY_TAG, "value 1 $reply ")

        }.await()
        Log.d(MY_TAG, "value 2 $value ")
        return value
    }

Log value 1 [http...]

Log value 2 []

Note: due to the function suspend!, to launch it I use runBlocking{}

runBlocking {
            getNetworkResponse()
}
0

The reason being that is that is not in the scope of coroutines. so it doesnt push either resume back it just go next next.....

Log array 2 []

As Reason below with explain of Suspending function , it will push and resumed at a later time when the job done. That why you see it log it being called after Log array 2[].

Log array 1 [https://..]

Since you tagged kotlin-coroutines, I assume you are using Retrofit for api call.

@GET("endpoint/video")
 suspend fun getVideo(): Response<List<Video>>

Suspending functions are at the center of everything coroutines. A suspending function is simply a function that can be paused and resumed at a later time. They can execute a long running operation and wait for it to complete without blocking.

For suspend function you only call it from coroutines scope. as it said paused and resumed after they done with execute . It will return the values once it done.

Base on your function you don't need to return values

    var array = listOf<String>()
    private fun getNetworkResponse() {
        viewModelScope.launch(Dispatchers.IO) { // Background Thread
            val list = api.getVideo().data?.map { it?.url }
            withContext(Dispatchers.Main) {
                array = list
                // update UI on Main Thread
            }
        }

    }

or another way is make getNetworkResponse() as suspend with return List

Example :

 private suspend fun getNetworkResponse(): List<String> {
    val list = api.getVideo().data
    return list?.map { it?.url } ?? emptyList<String>()
}
Nrohpos
  • 283
  • 2
  • 7