Reputation: 5497
I have a java class file which works fine, but if I convert it to Kotlin it makes some problem. Here is a Java version
public class CallbackWrapper<T> implements Callback<T> {
private Wrapper<T> wrapper;
public CallbackWrapper(Wrapper<T> wrapper) {
this.wrapper = wrapper;
}
public void onFailure(Call<T> call, Throwable t) {
wrapper.onResult(t, null);
}
public void onResponse(Call<T> call, Response<T> response) {
wrapper.onResult(null, response);
}
public interface Wrapper<T> {
void onResult(@Nullable Throwable t, @Nullable Response<T> response);
}
}
And this is how I'm using this class without any problem...
request.enqueue(CallbackWrapper<RegisterResponse> { throwable, response ->
response?.let { callBack.onResponse(response.body() ?: RegisterResponse()) }
throwable?.let { callBack.onFailed(throwable.message!!) }
})
And here is Kotlin version after converting
class CallbackWrapper<T>(private val wrapper: CallbackWrapper.Wrapper<T>) : Callback<T> {
override fun onFailure(call: Call<T>, t: Throwable) {
wrapper.onResult(t, null)
}
override fun onResponse(call: Call<T>, response: Response<T>) {
wrapper.onResult(null, response)
}
interface Wrapper<T> {
fun onResult(t: Throwable?, response: Response<T>?)
}
}
The problem is that after converting it to Kotlin, code block where I'm using this class were not working. I don't understand what is the difference between them.
Here is compile error log
Error:(17, 63) Type mismatch: inferred type is (???, ???) -> [ERROR :<ERROR FUNCTION RETURN TYPE>] but CallbackWrapper.Wrapper<RegisterResponse> was expected
Error:(17, 65) Cannot infer a type for this parameter. Please specify it explicitly.
Error:(17, 76) Cannot infer a type for this parameter. Please specify it explicitly.
Upvotes: 2
Views: 949
Reputation: 4233
You have two issues with your code, as far as I can tell.
First is that Kotlin doesn't allow using lambdas to implement Kotlin functional interfaces, so your lambda isn't going to work (it does allow implementing Java functional interfaces, because Java doesn't have proper function types). So to call the code unchanged, you want to use object notation instead:
request.enqueue(CallbackWrapper<RegisterResponse>(object : CallbackWrapper.Wrapper<RegisterResponse> {
override fun onResult(throwable: Throwable?, response: Response<RegisterResponse>?) {
response?.let { callBack.onResponse(response.body() ?: RegisterResponse()) }
throwable?.let { callBack.onFailure(throwable.message!!) }
}
}))
You can declare your CallbackWrapper
class differently if you prefer using lambdas:
typealias Wrapper<T> = (t: Throwable?, response: Response<T>?) -> Unit
class OtherCallbackWrapper<T>(val wrapper: Wrapper<T>) : Callback<T> {
override fun onFailure(call: Call<T>, t: Throwable) = wrapper.invoke(t, null)
override fun onResponse(call: Call<T>, response: Response<T>) = wrapper.invoke(null, response)
}
So that's the but CallbackWrapper.Wrapper<RegisterResponse> was expected
part taken care of.
This still won't work, though, which brings us to the reason the first half of the error message is inferred type is (???, ???) -> [ERROR :<ERROR FUNCTION RETURN TYPE>]
. That's basically type inference failing. The calls to callBack
don't quite seem to match the CallBack
interface implied by CallbackWrapper, which I expect might have something to do with it.
EDIT:
Added an answer to your Retrofit question with a more concise solution.
Upvotes: 3