T
T
Tsuzukeru2020-08-18 16:13:14
Android
Tsuzukeru, 2020-08-18 16:13:14

How to make main thread wait for CallBack when using Retrofit?

I'm using Retrofit to parse complex Json. You have to use a lot of nested loops in the deserializer, so the response comes slower than the main thread returns the result from the function.

override fun getVideoInfo(id: String): Video? {
        var video:Video? = Video(null)

      retrofitClient.getVideoInfo(id).enqueue(object : Callback<VideoItemResponse> {
            override fun onFailure(call: Call<VideoItemResponse>, t: Throwable) {
                video = null
                Log.e(VIDEO_ITEM_TAG, "Failure: $t.message" )
            }

            override fun onResponse(
                call: Call<VideoItemResponse>,
                response: Response<VideoItemResponse>
            ) {
                video = response.body()?.item
                Log.e(VIDEO_ITEM_TAG, "Response: ${video}")
            }
        })

        Log.e(VIDEO_ITEM_TAG, "Before return: ${video}")
        return video
    }


Here is the log:
2020-08-18 16:00:25.783 14824-14824/ru.app.yf E/Video item request: Before return: Video(videoId=null, title=null, duration=null, description=null, thumbnails={}, views=null)
2020-08-18 16:00:25.912 14824-14824/ru.app.yf E/Video item request: Response: Video(videoId=Chjs4xqYe0E, title=Влог из США. Я сделал ЭТО!, duration=PT15M37S, description=Регистрируйся в LetyShops и возвращай горящий кэшбэк


As you can see, the answer comes 129 milliseconds later. Tried to put the thread to sleep before return .

Thread.sleep(1000)
        Log.e(VIDEO_ITEM_TAG, "Before return: ${video}")
        return video


It did not help. How can this be resolved?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
N
Nikita, 2020-08-18
@Tsuzukeru

You call the request initially asynchronously with the enqueue() method. To run synchronously - use the execute() method. But as far as I know Android won't let you send a request on the UI thread.
PS
I would review the architecture of the application and instead of returning the received value in the method (via return), for example, directly in the callback, I would call another method, which would have received the answer.
You can also arrange all this more beautifully through RxJava + RxKotlin or coroutines.

A
alekseyHunter, 2020-08-19
@alekseyHunter

You have to use a lot of nested loops in the deserializer

What cycles?! Data-classes have been created and that's it. You need a list, make the List field inside the data class.
the response comes slower than the main thread, returns the result from the function.

How can you write bad code like that? You are calling a method that contains a callback. Until the method is processed, it will not return anything. Therefore, when you call for the first time, your object with Null will be returned to you. Use Null in Kotlin?! Was it created for this?
video = response.body()?.item

What is it?? Where checks on the code returned by the server? 400 error (code) will be returned by the server, and your program will crash!
Thread.sleep(1000)

Normally, the UI thread will slow down. And it's okay that the application will not respond to user actions for a second. Yes?!
Answer: Do all actions with the network asynchronously. Returned a retrofit response, checked it for correctness, called the method to update the ui there and sit back and enjoy.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question