Handle Retrofit Callback using Kotlin












0















Maybe this is a very easy topic but I cannot find the correct answer.



This is the deal, I was using this logic for handle API's into my current android project:




  • class SampleApi


  • interface ISampleApi


  • interface SampleClient


  • class GetUserData



Now that I'm moving to Kotlin, I cannot replicate the enqueue() function from retrofit into my Api class. This is an example of my code:



GetUserData.java:



class GetUserData {
private void tryGetData() {
sampleApi.getSomeData(userId, new Callback<Data>() {
@Override
public void onResponse(final Call<Data> call, final Response<Data> response) {
......Do Something
}

@Override
public void onFailure(final Call<Data> call, final Throwable t) {
......Do Something
}
});


I'm using a interface in order to declare the methods to be implemented into the API class:



public interface ISampleApi {

void getSomeData(@NonNull String userId,
@NonNull Callback<Data> callback);

}


This is my API class:



public class SampleApi implements ISampleApi {
............
@Override
public void getSomeData(@NonNull final String userId,
@NonNull final Callback<Data> callback) {
myClient.getSomeData(userId).enqueue(callback);
}
}


And this is MyClient using Retrofit:



public interface SampleClient {
@GET("user/data/{userId}")
Call<Data> getSomeData(@NonNull @Path("userId") String userId);
}


All the code above works fine, that's what I'm using in my app without problem.



Now, this is the problem when move to Kotlin, I'm try to create the enqueue callback into SampleApi and I need to return the response to the class where the callback was created, in Kotlin should be something like this:



fun getSomeData(userId: String, callback: CallBack<Data>) {
client?.getSomeData(userId).enqueue(callback)
}


But when try to do that, Android Studio tell me that I have to create a extension function, I create the extension function, and after more suggestion from Android Studio and some research the result is something like this:



override fun getSomeData(@NonNull userId: String,
@NonNull callback: Callback<Data>) {//Neve using this callback
client?.getSomeData(userId).enqueue {
success = {
success -> Do Something
}
failure = {
failure -> Do Something
}
}
}

fun<T> Call<T>.enqueue(callback: BaseCallback<T>.() -> Unit) {
val callbackBk = BaseCallback<T>()
callback.invoke(callbackBk)
this.enqueue(callbackBk)

}

class BaseCallback<T>: Callback<T> {
var success: ((Response<T>) -> Unit)? = null
var failure: ((t: Throwable?) -> Unit)? = null

override fun onFailure(call: Call<T>, t: Throwable) {
failure?.invoke(t)
}

override fun onResponse(call: Call<T>, response: Response<T>) {
success?.invoke(response)
}
}


BaseCallback.kt



open class BaseCallback<T: Validatable>(): Callback<BaseResponseBody<T>> {
var success: ((T) -> Unit)? = null
var failure: ((networkingError: NetworkingError?) -> Unit)? = null
override fun onResponse(call: Call<BaseResponseBody<T>>, response: Response<BaseResponseBody<T>>) {

if (response?.code() != null
&& response.isSuccessful
&& response.body() != null
&& response.body().containsValidSuccess()) run {

onSuccessfulResponse(response.body().data!!)
} else if (response != null
&& response.isSuccessful
&& response.body() != null) {

onSuccessfulResponse()
} else {
onNonSessionErrorEncountered(networkingError)
}
}

override fun onFailure(call: Call<BaseResponseBody<T>>, throwable: Throwable) {
onNonSessionErrorEncountered(NetworkStateError(throwable))
}

@VisibleForTesting(otherwise = PROTECTED)
fun onSuccessfulResponse(responseValue: T) {
success?.invoke(responseValue)
}

@VisibleForTesting(otherwise = PROTECTED)
fun onSuccessfulResponse() {
// This method intentionally left blank.
}

fun onSessionErrorEncountered() {
// This method intentionally left blank.
}

@VisibleForTesting(otherwise = PROTECTED)
fun onNonSessionErrorEncountered(networkingError: NetworkingError) {
failure?.invoke(networkingError)
}
}


This code works fine here, I can receive the data, but I need to receive the response inside the class that call this endpoint, since I need to change the UI.



I really appreciate a lot some help, I have been stuck with this for a while and I need to solve the issue to move on with the app.










share|improve this question

























  • Pass an interface object in fun getSomeData

    – Sreedev P R
    Nov 27 '18 at 4:43
















0















Maybe this is a very easy topic but I cannot find the correct answer.



This is the deal, I was using this logic for handle API's into my current android project:




  • class SampleApi


  • interface ISampleApi


  • interface SampleClient


  • class GetUserData



Now that I'm moving to Kotlin, I cannot replicate the enqueue() function from retrofit into my Api class. This is an example of my code:



GetUserData.java:



class GetUserData {
private void tryGetData() {
sampleApi.getSomeData(userId, new Callback<Data>() {
@Override
public void onResponse(final Call<Data> call, final Response<Data> response) {
......Do Something
}

@Override
public void onFailure(final Call<Data> call, final Throwable t) {
......Do Something
}
});


I'm using a interface in order to declare the methods to be implemented into the API class:



public interface ISampleApi {

void getSomeData(@NonNull String userId,
@NonNull Callback<Data> callback);

}


This is my API class:



public class SampleApi implements ISampleApi {
............
@Override
public void getSomeData(@NonNull final String userId,
@NonNull final Callback<Data> callback) {
myClient.getSomeData(userId).enqueue(callback);
}
}


And this is MyClient using Retrofit:



public interface SampleClient {
@GET("user/data/{userId}")
Call<Data> getSomeData(@NonNull @Path("userId") String userId);
}


All the code above works fine, that's what I'm using in my app without problem.



Now, this is the problem when move to Kotlin, I'm try to create the enqueue callback into SampleApi and I need to return the response to the class where the callback was created, in Kotlin should be something like this:



fun getSomeData(userId: String, callback: CallBack<Data>) {
client?.getSomeData(userId).enqueue(callback)
}


But when try to do that, Android Studio tell me that I have to create a extension function, I create the extension function, and after more suggestion from Android Studio and some research the result is something like this:



override fun getSomeData(@NonNull userId: String,
@NonNull callback: Callback<Data>) {//Neve using this callback
client?.getSomeData(userId).enqueue {
success = {
success -> Do Something
}
failure = {
failure -> Do Something
}
}
}

fun<T> Call<T>.enqueue(callback: BaseCallback<T>.() -> Unit) {
val callbackBk = BaseCallback<T>()
callback.invoke(callbackBk)
this.enqueue(callbackBk)

}

class BaseCallback<T>: Callback<T> {
var success: ((Response<T>) -> Unit)? = null
var failure: ((t: Throwable?) -> Unit)? = null

override fun onFailure(call: Call<T>, t: Throwable) {
failure?.invoke(t)
}

override fun onResponse(call: Call<T>, response: Response<T>) {
success?.invoke(response)
}
}


BaseCallback.kt



open class BaseCallback<T: Validatable>(): Callback<BaseResponseBody<T>> {
var success: ((T) -> Unit)? = null
var failure: ((networkingError: NetworkingError?) -> Unit)? = null
override fun onResponse(call: Call<BaseResponseBody<T>>, response: Response<BaseResponseBody<T>>) {

if (response?.code() != null
&& response.isSuccessful
&& response.body() != null
&& response.body().containsValidSuccess()) run {

onSuccessfulResponse(response.body().data!!)
} else if (response != null
&& response.isSuccessful
&& response.body() != null) {

onSuccessfulResponse()
} else {
onNonSessionErrorEncountered(networkingError)
}
}

override fun onFailure(call: Call<BaseResponseBody<T>>, throwable: Throwable) {
onNonSessionErrorEncountered(NetworkStateError(throwable))
}

@VisibleForTesting(otherwise = PROTECTED)
fun onSuccessfulResponse(responseValue: T) {
success?.invoke(responseValue)
}

@VisibleForTesting(otherwise = PROTECTED)
fun onSuccessfulResponse() {
// This method intentionally left blank.
}

fun onSessionErrorEncountered() {
// This method intentionally left blank.
}

@VisibleForTesting(otherwise = PROTECTED)
fun onNonSessionErrorEncountered(networkingError: NetworkingError) {
failure?.invoke(networkingError)
}
}


This code works fine here, I can receive the data, but I need to receive the response inside the class that call this endpoint, since I need to change the UI.



I really appreciate a lot some help, I have been stuck with this for a while and I need to solve the issue to move on with the app.










share|improve this question

























  • Pass an interface object in fun getSomeData

    – Sreedev P R
    Nov 27 '18 at 4:43














0












0








0








Maybe this is a very easy topic but I cannot find the correct answer.



This is the deal, I was using this logic for handle API's into my current android project:




  • class SampleApi


  • interface ISampleApi


  • interface SampleClient


  • class GetUserData



Now that I'm moving to Kotlin, I cannot replicate the enqueue() function from retrofit into my Api class. This is an example of my code:



GetUserData.java:



class GetUserData {
private void tryGetData() {
sampleApi.getSomeData(userId, new Callback<Data>() {
@Override
public void onResponse(final Call<Data> call, final Response<Data> response) {
......Do Something
}

@Override
public void onFailure(final Call<Data> call, final Throwable t) {
......Do Something
}
});


I'm using a interface in order to declare the methods to be implemented into the API class:



public interface ISampleApi {

void getSomeData(@NonNull String userId,
@NonNull Callback<Data> callback);

}


This is my API class:



public class SampleApi implements ISampleApi {
............
@Override
public void getSomeData(@NonNull final String userId,
@NonNull final Callback<Data> callback) {
myClient.getSomeData(userId).enqueue(callback);
}
}


And this is MyClient using Retrofit:



public interface SampleClient {
@GET("user/data/{userId}")
Call<Data> getSomeData(@NonNull @Path("userId") String userId);
}


All the code above works fine, that's what I'm using in my app without problem.



Now, this is the problem when move to Kotlin, I'm try to create the enqueue callback into SampleApi and I need to return the response to the class where the callback was created, in Kotlin should be something like this:



fun getSomeData(userId: String, callback: CallBack<Data>) {
client?.getSomeData(userId).enqueue(callback)
}


But when try to do that, Android Studio tell me that I have to create a extension function, I create the extension function, and after more suggestion from Android Studio and some research the result is something like this:



override fun getSomeData(@NonNull userId: String,
@NonNull callback: Callback<Data>) {//Neve using this callback
client?.getSomeData(userId).enqueue {
success = {
success -> Do Something
}
failure = {
failure -> Do Something
}
}
}

fun<T> Call<T>.enqueue(callback: BaseCallback<T>.() -> Unit) {
val callbackBk = BaseCallback<T>()
callback.invoke(callbackBk)
this.enqueue(callbackBk)

}

class BaseCallback<T>: Callback<T> {
var success: ((Response<T>) -> Unit)? = null
var failure: ((t: Throwable?) -> Unit)? = null

override fun onFailure(call: Call<T>, t: Throwable) {
failure?.invoke(t)
}

override fun onResponse(call: Call<T>, response: Response<T>) {
success?.invoke(response)
}
}


BaseCallback.kt



open class BaseCallback<T: Validatable>(): Callback<BaseResponseBody<T>> {
var success: ((T) -> Unit)? = null
var failure: ((networkingError: NetworkingError?) -> Unit)? = null
override fun onResponse(call: Call<BaseResponseBody<T>>, response: Response<BaseResponseBody<T>>) {

if (response?.code() != null
&& response.isSuccessful
&& response.body() != null
&& response.body().containsValidSuccess()) run {

onSuccessfulResponse(response.body().data!!)
} else if (response != null
&& response.isSuccessful
&& response.body() != null) {

onSuccessfulResponse()
} else {
onNonSessionErrorEncountered(networkingError)
}
}

override fun onFailure(call: Call<BaseResponseBody<T>>, throwable: Throwable) {
onNonSessionErrorEncountered(NetworkStateError(throwable))
}

@VisibleForTesting(otherwise = PROTECTED)
fun onSuccessfulResponse(responseValue: T) {
success?.invoke(responseValue)
}

@VisibleForTesting(otherwise = PROTECTED)
fun onSuccessfulResponse() {
// This method intentionally left blank.
}

fun onSessionErrorEncountered() {
// This method intentionally left blank.
}

@VisibleForTesting(otherwise = PROTECTED)
fun onNonSessionErrorEncountered(networkingError: NetworkingError) {
failure?.invoke(networkingError)
}
}


This code works fine here, I can receive the data, but I need to receive the response inside the class that call this endpoint, since I need to change the UI.



I really appreciate a lot some help, I have been stuck with this for a while and I need to solve the issue to move on with the app.










share|improve this question
















Maybe this is a very easy topic but I cannot find the correct answer.



This is the deal, I was using this logic for handle API's into my current android project:




  • class SampleApi


  • interface ISampleApi


  • interface SampleClient


  • class GetUserData



Now that I'm moving to Kotlin, I cannot replicate the enqueue() function from retrofit into my Api class. This is an example of my code:



GetUserData.java:



class GetUserData {
private void tryGetData() {
sampleApi.getSomeData(userId, new Callback<Data>() {
@Override
public void onResponse(final Call<Data> call, final Response<Data> response) {
......Do Something
}

@Override
public void onFailure(final Call<Data> call, final Throwable t) {
......Do Something
}
});


I'm using a interface in order to declare the methods to be implemented into the API class:



public interface ISampleApi {

void getSomeData(@NonNull String userId,
@NonNull Callback<Data> callback);

}


This is my API class:



public class SampleApi implements ISampleApi {
............
@Override
public void getSomeData(@NonNull final String userId,
@NonNull final Callback<Data> callback) {
myClient.getSomeData(userId).enqueue(callback);
}
}


And this is MyClient using Retrofit:



public interface SampleClient {
@GET("user/data/{userId}")
Call<Data> getSomeData(@NonNull @Path("userId") String userId);
}


All the code above works fine, that's what I'm using in my app without problem.



Now, this is the problem when move to Kotlin, I'm try to create the enqueue callback into SampleApi and I need to return the response to the class where the callback was created, in Kotlin should be something like this:



fun getSomeData(userId: String, callback: CallBack<Data>) {
client?.getSomeData(userId).enqueue(callback)
}


But when try to do that, Android Studio tell me that I have to create a extension function, I create the extension function, and after more suggestion from Android Studio and some research the result is something like this:



override fun getSomeData(@NonNull userId: String,
@NonNull callback: Callback<Data>) {//Neve using this callback
client?.getSomeData(userId).enqueue {
success = {
success -> Do Something
}
failure = {
failure -> Do Something
}
}
}

fun<T> Call<T>.enqueue(callback: BaseCallback<T>.() -> Unit) {
val callbackBk = BaseCallback<T>()
callback.invoke(callbackBk)
this.enqueue(callbackBk)

}

class BaseCallback<T>: Callback<T> {
var success: ((Response<T>) -> Unit)? = null
var failure: ((t: Throwable?) -> Unit)? = null

override fun onFailure(call: Call<T>, t: Throwable) {
failure?.invoke(t)
}

override fun onResponse(call: Call<T>, response: Response<T>) {
success?.invoke(response)
}
}


BaseCallback.kt



open class BaseCallback<T: Validatable>(): Callback<BaseResponseBody<T>> {
var success: ((T) -> Unit)? = null
var failure: ((networkingError: NetworkingError?) -> Unit)? = null
override fun onResponse(call: Call<BaseResponseBody<T>>, response: Response<BaseResponseBody<T>>) {

if (response?.code() != null
&& response.isSuccessful
&& response.body() != null
&& response.body().containsValidSuccess()) run {

onSuccessfulResponse(response.body().data!!)
} else if (response != null
&& response.isSuccessful
&& response.body() != null) {

onSuccessfulResponse()
} else {
onNonSessionErrorEncountered(networkingError)
}
}

override fun onFailure(call: Call<BaseResponseBody<T>>, throwable: Throwable) {
onNonSessionErrorEncountered(NetworkStateError(throwable))
}

@VisibleForTesting(otherwise = PROTECTED)
fun onSuccessfulResponse(responseValue: T) {
success?.invoke(responseValue)
}

@VisibleForTesting(otherwise = PROTECTED)
fun onSuccessfulResponse() {
// This method intentionally left blank.
}

fun onSessionErrorEncountered() {
// This method intentionally left blank.
}

@VisibleForTesting(otherwise = PROTECTED)
fun onNonSessionErrorEncountered(networkingError: NetworkingError) {
failure?.invoke(networkingError)
}
}


This code works fine here, I can receive the data, but I need to receive the response inside the class that call this endpoint, since I need to change the UI.



I really appreciate a lot some help, I have been stuck with this for a while and I need to solve the issue to move on with the app.







android kotlin retrofit






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 27 '18 at 5:17







Andrew

















asked Nov 27 '18 at 3:34









AndrewAndrew

84




84













  • Pass an interface object in fun getSomeData

    – Sreedev P R
    Nov 27 '18 at 4:43



















  • Pass an interface object in fun getSomeData

    – Sreedev P R
    Nov 27 '18 at 4:43

















Pass an interface object in fun getSomeData

– Sreedev P R
Nov 27 '18 at 4:43





Pass an interface object in fun getSomeData

– Sreedev P R
Nov 27 '18 at 4:43












1 Answer
1






active

oldest

votes


















0














Put below code in AppRepository.kt file



companion object { 

fun getServiceDetails(map: Map<String, String>, callback: ApiCallback<ServiceDetailsDataClass.ServiceDetailsResponse>) {
val retrofit = ApiClient.retrofit
val callGet = retrofit?.create<ApiService.ServiceDetails>(ApiService.ServiceDetails::class.java)?.getServiceDetails(map, ApiConstants.API_KEY, ApiConstants.API_LANG)

callGet?.enqueue(object : Callback<ServiceDetailsDataClass.ServiceDetailsResponse> {
override fun onFailure(call: Call<ServiceDetailsDataClass.ServiceDetailsResponse>?, t: Throwable?) {
callback.onError(t.toString())
}

override fun onResponse(call: Call<ServiceDetailsDataClass.ServiceDetailsResponse>?, response: Response<ServiceDetailsDataClass.ServiceDetailsResponse>?) {
if (response?.isSuccessful!!) {
callback.onSuccess(response.body()!!)
} else {
setError(callback, response)
}
}

})
}


ApiCallBack.kt interface file has the code:



interface ApiCallback<T> {
fun onException(error: Throwable)

fun onError(error: String)

fun onSuccess(t: T)


}



ApiService.kt file has the code:



 interface ApiService {

interface ServiceDetails {
@GET("api/path/here/")
fun getServiceDetails(@QueryMap map: Map<String, String>, @Header(ApiConstants.KEY_X_API) apiKey: String, @Header(ApiConstants.KEY_ACCEPT_LANGUAGE) language: String): Call<ServiceDetailsDataClass.ServiceDetailsResponse>
}


Now call api using :



AppRepository.getServiceDetails(map, object : ApiCallback<ServiceDetailsDataClass.ServiceDetailsResponse> {
override fun onException(error: Throwable) {
serviceDetailsResponse.value = error
}

override fun onError(error: String) {
serviceDetailsResponse.value = error
}

override fun onSuccess(t: ServiceDetailsDataClass.ServiceDetailsResponse) {
serviceDetailsResponse.value = t

}

})


Hope it helps you.






share|improve this answer
























  • Thanks a lot for your help @Vikash but I cannot replicate your logic into my code, seems like the logic is for one endpoint, what happened when you have more than one or more than ten, that's a lot of code. I was trying to replicate your logic into my code but I had some problems since I'm implementing my own BaseCallback.kt (put code above) and is not working, keep saying that I have to implement extension function.

    – Andrew
    Nov 27 '18 at 5:22











  • @Andrew So you send calls to different apis ?

    – Ashish
    Nov 27 '18 at 7:12











  • Same Api, but different endpoint, if I put everything into companion object{} will be a huge static class.

    – Andrew
    Nov 27 '18 at 14:58











  • @Andrew you can avoid companion object{} by using object class, and for different endpoints you have to use separate code, obviously. Or you have any other approach? want to know that too :)

    – Vikash Bijarniya
    Nov 28 '18 at 6:18











  • I solve the problem using Observables from RxJava, seems to work fine, I need to find the way to use BaseCallBack<T>. But that's another history.

    – Andrew
    Nov 28 '18 at 15:18











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53492348%2fhandle-retrofit-callback-using-kotlin%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














Put below code in AppRepository.kt file



companion object { 

fun getServiceDetails(map: Map<String, String>, callback: ApiCallback<ServiceDetailsDataClass.ServiceDetailsResponse>) {
val retrofit = ApiClient.retrofit
val callGet = retrofit?.create<ApiService.ServiceDetails>(ApiService.ServiceDetails::class.java)?.getServiceDetails(map, ApiConstants.API_KEY, ApiConstants.API_LANG)

callGet?.enqueue(object : Callback<ServiceDetailsDataClass.ServiceDetailsResponse> {
override fun onFailure(call: Call<ServiceDetailsDataClass.ServiceDetailsResponse>?, t: Throwable?) {
callback.onError(t.toString())
}

override fun onResponse(call: Call<ServiceDetailsDataClass.ServiceDetailsResponse>?, response: Response<ServiceDetailsDataClass.ServiceDetailsResponse>?) {
if (response?.isSuccessful!!) {
callback.onSuccess(response.body()!!)
} else {
setError(callback, response)
}
}

})
}


ApiCallBack.kt interface file has the code:



interface ApiCallback<T> {
fun onException(error: Throwable)

fun onError(error: String)

fun onSuccess(t: T)


}



ApiService.kt file has the code:



 interface ApiService {

interface ServiceDetails {
@GET("api/path/here/")
fun getServiceDetails(@QueryMap map: Map<String, String>, @Header(ApiConstants.KEY_X_API) apiKey: String, @Header(ApiConstants.KEY_ACCEPT_LANGUAGE) language: String): Call<ServiceDetailsDataClass.ServiceDetailsResponse>
}


Now call api using :



AppRepository.getServiceDetails(map, object : ApiCallback<ServiceDetailsDataClass.ServiceDetailsResponse> {
override fun onException(error: Throwable) {
serviceDetailsResponse.value = error
}

override fun onError(error: String) {
serviceDetailsResponse.value = error
}

override fun onSuccess(t: ServiceDetailsDataClass.ServiceDetailsResponse) {
serviceDetailsResponse.value = t

}

})


Hope it helps you.






share|improve this answer
























  • Thanks a lot for your help @Vikash but I cannot replicate your logic into my code, seems like the logic is for one endpoint, what happened when you have more than one or more than ten, that's a lot of code. I was trying to replicate your logic into my code but I had some problems since I'm implementing my own BaseCallback.kt (put code above) and is not working, keep saying that I have to implement extension function.

    – Andrew
    Nov 27 '18 at 5:22











  • @Andrew So you send calls to different apis ?

    – Ashish
    Nov 27 '18 at 7:12











  • Same Api, but different endpoint, if I put everything into companion object{} will be a huge static class.

    – Andrew
    Nov 27 '18 at 14:58











  • @Andrew you can avoid companion object{} by using object class, and for different endpoints you have to use separate code, obviously. Or you have any other approach? want to know that too :)

    – Vikash Bijarniya
    Nov 28 '18 at 6:18











  • I solve the problem using Observables from RxJava, seems to work fine, I need to find the way to use BaseCallBack<T>. But that's another history.

    – Andrew
    Nov 28 '18 at 15:18
















0














Put below code in AppRepository.kt file



companion object { 

fun getServiceDetails(map: Map<String, String>, callback: ApiCallback<ServiceDetailsDataClass.ServiceDetailsResponse>) {
val retrofit = ApiClient.retrofit
val callGet = retrofit?.create<ApiService.ServiceDetails>(ApiService.ServiceDetails::class.java)?.getServiceDetails(map, ApiConstants.API_KEY, ApiConstants.API_LANG)

callGet?.enqueue(object : Callback<ServiceDetailsDataClass.ServiceDetailsResponse> {
override fun onFailure(call: Call<ServiceDetailsDataClass.ServiceDetailsResponse>?, t: Throwable?) {
callback.onError(t.toString())
}

override fun onResponse(call: Call<ServiceDetailsDataClass.ServiceDetailsResponse>?, response: Response<ServiceDetailsDataClass.ServiceDetailsResponse>?) {
if (response?.isSuccessful!!) {
callback.onSuccess(response.body()!!)
} else {
setError(callback, response)
}
}

})
}


ApiCallBack.kt interface file has the code:



interface ApiCallback<T> {
fun onException(error: Throwable)

fun onError(error: String)

fun onSuccess(t: T)


}



ApiService.kt file has the code:



 interface ApiService {

interface ServiceDetails {
@GET("api/path/here/")
fun getServiceDetails(@QueryMap map: Map<String, String>, @Header(ApiConstants.KEY_X_API) apiKey: String, @Header(ApiConstants.KEY_ACCEPT_LANGUAGE) language: String): Call<ServiceDetailsDataClass.ServiceDetailsResponse>
}


Now call api using :



AppRepository.getServiceDetails(map, object : ApiCallback<ServiceDetailsDataClass.ServiceDetailsResponse> {
override fun onException(error: Throwable) {
serviceDetailsResponse.value = error
}

override fun onError(error: String) {
serviceDetailsResponse.value = error
}

override fun onSuccess(t: ServiceDetailsDataClass.ServiceDetailsResponse) {
serviceDetailsResponse.value = t

}

})


Hope it helps you.






share|improve this answer
























  • Thanks a lot for your help @Vikash but I cannot replicate your logic into my code, seems like the logic is for one endpoint, what happened when you have more than one or more than ten, that's a lot of code. I was trying to replicate your logic into my code but I had some problems since I'm implementing my own BaseCallback.kt (put code above) and is not working, keep saying that I have to implement extension function.

    – Andrew
    Nov 27 '18 at 5:22











  • @Andrew So you send calls to different apis ?

    – Ashish
    Nov 27 '18 at 7:12











  • Same Api, but different endpoint, if I put everything into companion object{} will be a huge static class.

    – Andrew
    Nov 27 '18 at 14:58











  • @Andrew you can avoid companion object{} by using object class, and for different endpoints you have to use separate code, obviously. Or you have any other approach? want to know that too :)

    – Vikash Bijarniya
    Nov 28 '18 at 6:18











  • I solve the problem using Observables from RxJava, seems to work fine, I need to find the way to use BaseCallBack<T>. But that's another history.

    – Andrew
    Nov 28 '18 at 15:18














0












0








0







Put below code in AppRepository.kt file



companion object { 

fun getServiceDetails(map: Map<String, String>, callback: ApiCallback<ServiceDetailsDataClass.ServiceDetailsResponse>) {
val retrofit = ApiClient.retrofit
val callGet = retrofit?.create<ApiService.ServiceDetails>(ApiService.ServiceDetails::class.java)?.getServiceDetails(map, ApiConstants.API_KEY, ApiConstants.API_LANG)

callGet?.enqueue(object : Callback<ServiceDetailsDataClass.ServiceDetailsResponse> {
override fun onFailure(call: Call<ServiceDetailsDataClass.ServiceDetailsResponse>?, t: Throwable?) {
callback.onError(t.toString())
}

override fun onResponse(call: Call<ServiceDetailsDataClass.ServiceDetailsResponse>?, response: Response<ServiceDetailsDataClass.ServiceDetailsResponse>?) {
if (response?.isSuccessful!!) {
callback.onSuccess(response.body()!!)
} else {
setError(callback, response)
}
}

})
}


ApiCallBack.kt interface file has the code:



interface ApiCallback<T> {
fun onException(error: Throwable)

fun onError(error: String)

fun onSuccess(t: T)


}



ApiService.kt file has the code:



 interface ApiService {

interface ServiceDetails {
@GET("api/path/here/")
fun getServiceDetails(@QueryMap map: Map<String, String>, @Header(ApiConstants.KEY_X_API) apiKey: String, @Header(ApiConstants.KEY_ACCEPT_LANGUAGE) language: String): Call<ServiceDetailsDataClass.ServiceDetailsResponse>
}


Now call api using :



AppRepository.getServiceDetails(map, object : ApiCallback<ServiceDetailsDataClass.ServiceDetailsResponse> {
override fun onException(error: Throwable) {
serviceDetailsResponse.value = error
}

override fun onError(error: String) {
serviceDetailsResponse.value = error
}

override fun onSuccess(t: ServiceDetailsDataClass.ServiceDetailsResponse) {
serviceDetailsResponse.value = t

}

})


Hope it helps you.






share|improve this answer













Put below code in AppRepository.kt file



companion object { 

fun getServiceDetails(map: Map<String, String>, callback: ApiCallback<ServiceDetailsDataClass.ServiceDetailsResponse>) {
val retrofit = ApiClient.retrofit
val callGet = retrofit?.create<ApiService.ServiceDetails>(ApiService.ServiceDetails::class.java)?.getServiceDetails(map, ApiConstants.API_KEY, ApiConstants.API_LANG)

callGet?.enqueue(object : Callback<ServiceDetailsDataClass.ServiceDetailsResponse> {
override fun onFailure(call: Call<ServiceDetailsDataClass.ServiceDetailsResponse>?, t: Throwable?) {
callback.onError(t.toString())
}

override fun onResponse(call: Call<ServiceDetailsDataClass.ServiceDetailsResponse>?, response: Response<ServiceDetailsDataClass.ServiceDetailsResponse>?) {
if (response?.isSuccessful!!) {
callback.onSuccess(response.body()!!)
} else {
setError(callback, response)
}
}

})
}


ApiCallBack.kt interface file has the code:



interface ApiCallback<T> {
fun onException(error: Throwable)

fun onError(error: String)

fun onSuccess(t: T)


}



ApiService.kt file has the code:



 interface ApiService {

interface ServiceDetails {
@GET("api/path/here/")
fun getServiceDetails(@QueryMap map: Map<String, String>, @Header(ApiConstants.KEY_X_API) apiKey: String, @Header(ApiConstants.KEY_ACCEPT_LANGUAGE) language: String): Call<ServiceDetailsDataClass.ServiceDetailsResponse>
}


Now call api using :



AppRepository.getServiceDetails(map, object : ApiCallback<ServiceDetailsDataClass.ServiceDetailsResponse> {
override fun onException(error: Throwable) {
serviceDetailsResponse.value = error
}

override fun onError(error: String) {
serviceDetailsResponse.value = error
}

override fun onSuccess(t: ServiceDetailsDataClass.ServiceDetailsResponse) {
serviceDetailsResponse.value = t

}

})


Hope it helps you.







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 27 '18 at 4:20









Vikash BijarniyaVikash Bijarniya

1368




1368













  • Thanks a lot for your help @Vikash but I cannot replicate your logic into my code, seems like the logic is for one endpoint, what happened when you have more than one or more than ten, that's a lot of code. I was trying to replicate your logic into my code but I had some problems since I'm implementing my own BaseCallback.kt (put code above) and is not working, keep saying that I have to implement extension function.

    – Andrew
    Nov 27 '18 at 5:22











  • @Andrew So you send calls to different apis ?

    – Ashish
    Nov 27 '18 at 7:12











  • Same Api, but different endpoint, if I put everything into companion object{} will be a huge static class.

    – Andrew
    Nov 27 '18 at 14:58











  • @Andrew you can avoid companion object{} by using object class, and for different endpoints you have to use separate code, obviously. Or you have any other approach? want to know that too :)

    – Vikash Bijarniya
    Nov 28 '18 at 6:18











  • I solve the problem using Observables from RxJava, seems to work fine, I need to find the way to use BaseCallBack<T>. But that's another history.

    – Andrew
    Nov 28 '18 at 15:18



















  • Thanks a lot for your help @Vikash but I cannot replicate your logic into my code, seems like the logic is for one endpoint, what happened when you have more than one or more than ten, that's a lot of code. I was trying to replicate your logic into my code but I had some problems since I'm implementing my own BaseCallback.kt (put code above) and is not working, keep saying that I have to implement extension function.

    – Andrew
    Nov 27 '18 at 5:22











  • @Andrew So you send calls to different apis ?

    – Ashish
    Nov 27 '18 at 7:12











  • Same Api, but different endpoint, if I put everything into companion object{} will be a huge static class.

    – Andrew
    Nov 27 '18 at 14:58











  • @Andrew you can avoid companion object{} by using object class, and for different endpoints you have to use separate code, obviously. Or you have any other approach? want to know that too :)

    – Vikash Bijarniya
    Nov 28 '18 at 6:18











  • I solve the problem using Observables from RxJava, seems to work fine, I need to find the way to use BaseCallBack<T>. But that's another history.

    – Andrew
    Nov 28 '18 at 15:18

















Thanks a lot for your help @Vikash but I cannot replicate your logic into my code, seems like the logic is for one endpoint, what happened when you have more than one or more than ten, that's a lot of code. I was trying to replicate your logic into my code but I had some problems since I'm implementing my own BaseCallback.kt (put code above) and is not working, keep saying that I have to implement extension function.

– Andrew
Nov 27 '18 at 5:22





Thanks a lot for your help @Vikash but I cannot replicate your logic into my code, seems like the logic is for one endpoint, what happened when you have more than one or more than ten, that's a lot of code. I was trying to replicate your logic into my code but I had some problems since I'm implementing my own BaseCallback.kt (put code above) and is not working, keep saying that I have to implement extension function.

– Andrew
Nov 27 '18 at 5:22













@Andrew So you send calls to different apis ?

– Ashish
Nov 27 '18 at 7:12





@Andrew So you send calls to different apis ?

– Ashish
Nov 27 '18 at 7:12













Same Api, but different endpoint, if I put everything into companion object{} will be a huge static class.

– Andrew
Nov 27 '18 at 14:58





Same Api, but different endpoint, if I put everything into companion object{} will be a huge static class.

– Andrew
Nov 27 '18 at 14:58













@Andrew you can avoid companion object{} by using object class, and for different endpoints you have to use separate code, obviously. Or you have any other approach? want to know that too :)

– Vikash Bijarniya
Nov 28 '18 at 6:18





@Andrew you can avoid companion object{} by using object class, and for different endpoints you have to use separate code, obviously. Or you have any other approach? want to know that too :)

– Vikash Bijarniya
Nov 28 '18 at 6:18













I solve the problem using Observables from RxJava, seems to work fine, I need to find the way to use BaseCallBack<T>. But that's another history.

– Andrew
Nov 28 '18 at 15:18





I solve the problem using Observables from RxJava, seems to work fine, I need to find the way to use BaseCallBack<T>. But that's another history.

– Andrew
Nov 28 '18 at 15:18




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53492348%2fhandle-retrofit-callback-using-kotlin%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Contact image not getting when fetch all contact list from iPhone by CNContact

count number of partitions of a set with n elements into k subsets

A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks