0

Occasionally getting the Response in JSON format can take a few minutes because the JSON can have multiple objects in it.

My goal is to show the progress of getting the Response.

For this purpose I simplify my example of getting the Response using Retrofit.

UserApi

@GET("users")
    @Headers(
        "Accept:$HEADERS_ACCEPT", "Content-Type:$HEADERS_CONTENT_TYPE",
        "Authorization: $AUTHORISATION_TYPE $API_KEY"
    )
    fun getUsersList(@Query("page") pageNo: String, @Query("per_page") perPageNo: String): Call<List<User>>

Repository:

 override suspend fun getUsersList(pageNo: String , perPageNo: String,
                                      usersLiveData: MutableLiveData<List<User>?>) = withContext(ioDispatcher) {

        val call = retrofitUserApiInstance.getUsersList(pageNo, perPageNo)

        call.enqueue(object : Callback<List<User>> {
            override fun onFailure(call: Call<List<User>>, t: Throwable) {
                usersLiveData.postValue(null)
            }

            override fun onResponse(call: Call<List<User>>, response: Response<List<User>>) {
                if (response.isSuccessful) {
                    usersLiveData.postValue(response.body())
                } else {
                    usersLiveData.postValue(null)
                }
            }
        })
    }
DevPeter
  • 83
  • 2
  • 8
  • By "few minutes", do you actually mean a "few seconds", or is this several gigabytes of JSON? By the way, do not combine `enqueue` with a suspend function. Use `await()` instead. `enqueue` is asynchronous, but suspend functions are supposed to be synchronous. – Tenfour04 May 10 '23 at 13:48
  • Maybe a duplicate of https://stackoverflow.com/questions/42118924/android-retrofit-download-progress – Tenfour04 May 10 '23 at 13:52
  • Thank you for your response. Unfortunately getting the Response takes a few minutes because the computer "server" software is very very slow. The response data are only 5MB. The link that you send me points to a specific file (file name), so I am not sure how to use it in my example. Could you give me an example of how to rewrite my code to use the await() please? I am using suspend fun getUsersList because I try to be main-safe and these functions start in ViewModel inside the viewModelScope.launch { – DevPeter May 10 '23 at 15:26
  • 1
    Making a call with `enqueue` is main-safe because it's asynchronous, so maybe you don't need a suspend function anyway. It doesn't make any sense to use a suspend function to make an asynchronous call. Nothing above takes advantage of the `suspend` keyword. Suspend functions are for doing slow things synchronously without blocking. Here's how you'd do this with a suspend function synchronously. Note there is no livedata used because it just directly returns the result (or null for an error). And we don't use `withContext` because no blocking code is called. https://pastebin.com/5twxHsrf – Tenfour04 May 10 '23 at 17:47
  • You can also define your retrofit getter function to be a `suspend` function that returns `List` instead of a non-suspend function that returns `Call>` to streamline this further. But none of what I'm saying deals with the task of getting progress while it's going. That doesn't lend itself well to a suspend function. Maybe a Flow, but I don't know how to build it. I don't know how to do a GET request with progress updates. – Tenfour04 May 10 '23 at 17:47
  • Yes, you are right, I learn something new today. I change my suspend fun to fun. Also, I deleted the = withContext(ioDispatcher) from my function. Inside my function, I am setting my mutable live data to Observe them in Activity. For example: val outputSuccess: RetrofitRepositoryStatus = RetrofitRepositoryStatus.SUCCESS( responseBody, RetrofitRepositoryStatus.SUCCESS.Type.API_POST ) _getApiState.postValue(outputSuccess) Asynchronous Requests Example: https://futurestud.io/tutorials/retrofit-synchronous-and-asynchronous-requests – DevPeter May 10 '23 at 18:41

0 Answers0