Parag Pawar
Parag Pawar

Reputation: 857

"Resolved" Retrofit with Kotlin does not trigger enqueue

[Please check the update 2]

I'm trying to implement retrofit with Kotlin. Please look at the following code:

Here is the main retrofit method which should get the user from API(Webservice):

const val BASE_URL = "https://jsonplaceholder.typicode.com"

fun getUser(userId: Int){
    val loggingInterceptor = HttpLoggingInterceptor()
    loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
    val client = OkHttpClient.Builder()
        .connectTimeout(60, TimeUnit.SECONDS)
        .writeTimeout(60, TimeUnit.SECONDS)
        .readTimeout(60, TimeUnit.SECONDS)
        .addInterceptor(loggingInterceptor)
        .build()

    val retrofit = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .client(client)
        .addConverterFactory(GsonConverterFactory.create())
        .build()

     val user = retrofit.create(Api::class.java)

        val userObject : Call<ResponseBody> =  user.getUser(userId)

        userObject.enqueue(object : Callback<ResponseBody>{
            override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
                e(javaClass.simpleName, "loginResponse: $call")
                e(javaClass.simpleName, "loginResponse: ${t.printStackTrace()}")
            }

            override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
                e(javaClass.simpleName, "loginResponse: ${response.raw()}")
                e(javaClass.simpleName, "loginResponse: ${response.code()}")
                e(javaClass.simpleName, "loginResponse: ${response.message()}")
            }

        })

}

Api interface:

interface Api {

    @GET("users/{id}")
    fun getUser(
        @Path("id") id: Int
    ): Call<ResponseBody>
}

Now the issue is with the callback method of enqueue, onResponse and onFailure does not print any logs. But I get the logs the Http request is successful from OkHttpClient. If I use equivalent java code everything works just fine. I've spent an entire day searching for the solution. and tried different approaches, but nothing seems to work. Any help would be much appreciated.

UPDATE:

For now, I'm using it's equivalent Java code as follows which works great:

    userObject.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(@NotNull Call<ResponseBody> call, @NotNull Response<ResponseBody> response) {
            e(TAG, "loginResponse: " + call);
            e(TAG, "loginResponse: " + response.string());

        }

        @Override
        public void onFailure(@NotNull Call<ResponseBody> call, @NotNull Throwable t) {
            e(TAG, "loginResponse: " + call);
            e(TAG, "loginResponse: ", t);
        }
    });

Though I'm keeping this question unresolved, somebody might find/know a solution for it. Or If I find it in future I'll update it.

UPDATE 2

It was a silly mistake, or I can't even say it was a mistake. Actually what happened is logs were not getting printed from those methods. But when I put Toast inside those methods, it displayed the toast with the response.

So, I learned that Android Logs are not always reliable, so when you're stuck with the logs, always try and use toasts or interface methods. So this is the answer to my question.

But anybody could tell me why those logs didn't print, that would be very helpful too.

Upvotes: 1

Views: 4069

Answers (2)

Enselic
Enselic

Reputation: 4912

I tested your code and had to make some changes for it to work.

First, I had to define my own data class ResponseBody(val id: Int, val name: String) class (I was too lazy to add all fields). It did not work when I used okhttp3.ResponseBody.

And to get it to print the data that is returned, you have to change ${response.message()} to ${response.body()}.

In the Java code you posted, you use response.string(), which is different from response.message() in your Kotlin code.

Upvotes: 1

Efe Budak
Efe Budak

Reputation: 659

Try to define your method parameters as nullable;

userObject.enqueue(object : Callback<ResponseBody>{
        override fun onFailure(call: Call<ResponseBody>?, t: Throwable?) {
            e(javaClass.simpleName, "loginResponse: $call")
            e(javaClass.simpleName, "loginResponse: ${t.printStackTrace()}")
        }

        override fun onResponse(call: Call<ResponseBody>?, response: Response<ResponseBody>?) {
            e(javaClass.simpleName, "loginResponse: ${response.raw()}")
            e(javaClass.simpleName, "loginResponse: ${response.code()}")
            e(javaClass.simpleName, "loginResponse: ${response.message()}")
        }

    })

Since the Callback interface is defined in java those parameters are not nonnull.

Upvotes: 0

Related Questions