Search code examples
androidkotlinretrofitretrofit2

Custom Implementation of Callback for Retrofit in Kotlin


I have recently started with Kotlin for my android development and have faced minor issues which by using documentation I was able to solve, but with Retrofit Callback implementation I am facing a problem. I have a custom implementation for the Retrofit callback that I use in Java:

public abstract class RemoteCallback<T> implements Callback<T> {
@Override
public final void onResponse(Call<T> call, Response<T> response) {

    switch (response.code()) {
        case HttpsURLConnection.HTTP_OK:
        case HttpsURLConnection.HTTP_CREATED:
        case HttpsURLConnection.HTTP_ACCEPTED:
        case HttpsURLConnection.HTTP_NOT_AUTHORITATIVE:
            if (response.body() != null) {
                onSuccess(response.body());
            }
            break;
        case HttpURLConnection.HTTP_UNAUTHORIZED:
            onUnauthorized();
            break;
        default:
            onFailed(new Throwable("Default " + response.code() + " " + response.message()));
    }
}

@Override
public final void onFailure(Call<T> call, Throwable t) {
    onFailed(t);
}

public abstract void onSuccess(T responseBody);

public abstract void onUnauthorized();

public abstract void onFailed(Throwable throwable);}

I used the same class in Kotlin Project which in return converted the java code to kotlin code

abstract class RemoteCallback<T> : Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {

    when (response.code()) {
        HttpsURLConnection.HTTP_OK,
        HttpsURLConnection.HTTP_CREATED,
        HttpsURLConnection.HTTP_ACCEPTED,
        HttpsURLConnection.HTTP_NOT_AUTHORITATIVE ->
            if (response.body() != null)
            onSuccess(response.body())
        HttpURLConnection.HTTP_UNAUTHORIZED -> onUnauthorized()
        else -> onFailed(Throwable("Default " + response.code() + " " + response.message()))
    }
}

override fun onFailure(call: Call<T>, t: Throwable) {
    onFailed(t)
}

abstract fun onSuccess(responseBody: T)

abstract fun onUnauthorized()

abstract fun onFailed(throwable: Throwable)}

The problem is when I call onSucess(response.body()) as it says "Smart cast to 'T' is impossible, because 'response.body()' is a complex expression" Problem Please guide me on how to fix it


Solution

  • You are sending a Nullable value to a NonNull function as parameter. Therefore, you are getting that issue. You can go about this like:

    interface RemoteCallback<T> : Callback<T> {
        override fun onResponse(call: Call<T>?, response: Response<T>?) {
            when (response?.code()) {
                HttpsURLConnection.HTTP_OK,    
                HttpsURLConnection.HTTP_CREATED,
                HttpsURLConnection.HTTP_ACCEPTED,
                HttpsURLConnection.HTTP_NOT_AUTHORITATIVE ->
                    response.body()?.apply { onSuccess(this) }
                HttpURLConnection.HTTP_UNAUTHORIZED -> onUnauthorized()
                else -> onFailed(Throwable("Default " + response?.code() + " " + response?.message()))
            }
        }
    
        override fun onFailure(call: Call<T>?, t: Throwable?) {
            // handle error mechanism
            t?.apply { onFailed(this) }    
        }
        fun onSuccess(responseBody: T)
        fun onUnauthorized()
        fun onFailed(throwable: Throwable)
    }
    

    Alternatively, you can just use onSuccess(responseBody: T?) and your code should work