Retrofit: Kotlin support : implemented method in the interface throws an exception at runtime

Created on 16 Apr 2018  路  1Comment  路  Source: square/retrofit

I don't know if this really is a bug, a feature request or a question so please feel free to dispatch me elsewhere if needed.

At the moment, I would like to have the following kotlin code :

@POST("registrations/{id}")
fun register(@Path("id") id: String, @Body f: RegisterForm): Call<RegisterResponse>

fun registerDesc(id:String, f: RegisterForm) = ApiDesc(
        HttpMethod.POST, "registrations/{id}".replace("{id}", id), f.toJson()
)

the problem is that when I invoke the method registerDesc (at runtime), I get

 java.lang.IllegalArgumentException: Unable to create call adapter for class com.beasyness.beasynessandroid.ApiDesc
    for method RestApiService.registerDesc

Now, I know that with java 1.8+ I could add annotation JvmDefault above the registerDesc method (thus, from what I understand from #998, it would be correctly ignored by retrofit)

The problem is that I use Retrofit on Android which is not 1.8+

So is there a way to tell retrofit to ignore a method of the interface.

At the moment, I simply add a companion object to my interface but the problem is that the API and the desc are far away from each other (the more methods there is in the interface, the more space between the two)

Any advise ?

Most helpful comment

The reason this happens is that the interface is given that function as a normal abstract one and the implementation is copied to a $DefaultImpl nested class which any implementing types then call (unless you override).

I don't see any way to have this work aside from using the forthcoming @JvmDefault annotation in 1.2.40 (experimental) / 1.3 to get a proper default method the same as you would in Java. Android has support for this from API 24 and newer but if your minSdk is lower than that then you're out of luck.

An easy workaround is to use an extension method, but that also removes the functions from being defined in close proximity to each other.

>All comments

The reason this happens is that the interface is given that function as a normal abstract one and the implementation is copied to a $DefaultImpl nested class which any implementing types then call (unless you override).

I don't see any way to have this work aside from using the forthcoming @JvmDefault annotation in 1.2.40 (experimental) / 1.3 to get a proper default method the same as you would in Java. Android has support for this from API 24 and newer but if your minSdk is lower than that then you're out of luck.

An easy workaround is to use an extension method, but that also removes the functions from being defined in close proximity to each other.

Was this page helpful?
0 / 5 - 0 ratings