1

I need to do the next:

  1. Check is exist profile
  2. If exist then start async http request (getAdvertising()) by Retrofit lib
  3. if not exist then first loading profile from remote (by Retrofit) AND if success get result then start async http request (getAdvertising())

I do this by callback like this:

    fun getAdvertising(callback: Callback<List<Advertising>>) {
        val call = myRestClient.advertising
        executeAsync(call, callback)
    }

  private fun <T> executeAsync(call: Call<T>, callback: Callback<T>) {
        val currentApplicationProfileResponse = foService.applicationProfileResponse
        if (currentApplicationProfileResponse == null) {
            getApplicationProfile(object : DefaultRestClientCallback<ApplicationProfileResponse>() {

                override fun onTransportResponse(transportResponse: TransportResponse) {
                    super.onTransportResponse(transportResponse)
                    if (transportResponse.isSuccessful) {
                        //asynchronously
                        call.enqueue(callback)
                    } else { // not success
                        if (callback is DefaultRestClientCallback<*>) {
                            callback.onTransportResponse(transportResponse)
                        } else {
                            callback.onResponse(call, transportResponse.originalResponse as Response<T>?)
                        }
                    }
                }
            })
        } else { // appProfile is not null
            //asynchronously
            call.enqueue(callback)
        }
    }

Nice it's work fine.

But is to much code. Is it possible to repalace Callback by Kotlin's coroutines?

2

3 Answers 3

3
private fun getADvertise(onResult: (ArrayList<String>) -> Unit = {}) {
    CoroutineScope(Dispatchers.IO).launch {
        //Do Request To get Data using retrofit
        val result = ArrayList<String>()//result from retrofit
        withContext(Dispatchers.Main)
        {
            onResult(result)
        }

    }
}

private fun isProfileExist(): Boolean {
    //true or false
    return true
}

private fun getProfilePicture(id: String, OnResult: (String) -> Unit = {}) {
    CoroutineScope(Dispatchers.IO).launch {
        //Do Request To get Data using retrofit
        val result = "Link"//result from retrofit
        withContext(Dispatchers.Main)
        {
            OnResult(result)
        }

    }
}

//---------your main function------------------>
public fun execute(onResultMain: (ArrayList<String>) -> Unit = {}) {
    val exist = isProfileExist()
    if (exist) {
        getADvertise(onResultMain)
    } else {
        getProfilePicture("id") {

            getADvertise(onResultMain)
        }
    }

}
//onResultMain -> call back used to get result when they are ready ;) 
Sign up to request clarification or add additional context in comments.

Comments

2

Use call.execute() ( i.e, synchronous retrofit request ) inside suspend function of coroutine.

 suspend fun <T> executeAsync(call: Call<T>, callback: Callback<T>) {
       try {
           if(foService.applicationProfileResponse != null) {
              if(T is List<Advertising>) {
                 val advertisings = call.execute() // synchronous call 
              } 
           }
       } catch(e : Exception) {
           // handle exception
       } 
 }

Or, add

   .addCallAdapterFactory(CoroutineCallAdapterFactory())

to retrofit builder and use .await() with deferred

    call.await() // call is of type deferred 

Comments

1

you can use this way

suspend fun <T> Call<T>.getResult(): T = suspendCoroutine { cont ->
    enqueue(object : Callback<T> {
        override fun onFailure(call: Call<T>, t: Throwable) {
            cont.resumeWithException(t)
        }

        override fun onResponse(call: Call<T>, response: Response<T>) {
            if (response.isSuccessful) {
                cont.resume(response.body()!!)
            } else {
                cont.resumeWithException(ErrorResponse(response.message(), response.code()))
            }
        }

    })
}
class ErrorResponse(message: String, code: Int) : Throwable(message )

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.