Использование модифицированной методики более выразительный способ
Я хочу сделать void enqueue(Callback<T> callback);
метод вызова блока кода более выразительным, вот что у меня обычно
request.enqueue(object : Callback<MyModel> {
override fun onFailure(call: Call<MyModel>?, t: Throwable?) {
//
}
override fun onResponse(call: Call<MyModel>?, response: Response<MyModel>?) {
//
}
})
И что хотят и имеют в виду, чтобы изменить этот код блоков более чистым способом и удалить эти переопределение, объект, обратный вызов ключевые слова и сделать что-то вроде этого:
request.enqueue({throwable, response -> })
Я думаю, что его можно как-то улучшить, используя расширения и функции более высокого порядка. Кто-нибудь знает, как это можно сделать?
3 ответа:
Дана следующая функция:
fun <T> callback(fn: (Throwable?, Response<T>?) -> Unit): Callback<T> { return object : Callback<T> { override fun onResponse(call: Call<T>, response: retrofit2.Response<T>) = fn(null, response) override fun onFailure(call: Call<T>, t: Throwable) = fn(t, null) } }
Вы можете использовать это при модернизации следующим образом:
request.enqueue(callback({ throwable, response -> response?.let { callBack.onResponse(response.body() ?: RegisterResponse()) } throwable?.let { callBack.onFailed(throwable.message!!) })
Альтернативно, вы можете определить эту другую версию обратного вызова:
fun <T> callback2(success: ((Response<T>) -> Unit)?, failure: ((t: Throwable) -> Unit)? = null): Callback<T> { return object : Callback<T> { override fun onResponse(call: Call<T>, response: retrofit2.Response<T>) { success?.invoke(response) } override fun onFailure(call: Call<T>, t: Throwable) { failure?.invoke(t) } } }
который может быть использован следующим образом:request.enqueue(callback2( { r -> callBack.onResponse(r.body()) }, { t -> callBack.onFailed(t.message) }))
Вот что вы можете сделать (это Java, так как я не знаю много Kotlin, но это должно быть очень похоже):
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 static interface Wrapper<T> { void onResult(Throwable t, Response<T> response); } }
Который вы можете использовать как:
call.enqueue(new CallbackWrapper((throwable, reponse) - > {...}));
Обновление решения для kotlin:
На основе этого ,
CallBackWrapper
выглядит следующим образом:typealias wrapper<T> = (t: Throwable?, response: Response<T>?) -> Unit class CallbackWrapper<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) }
И использовать его так же, как Java.
Я использовал функцию расширения на
Call
, чтобы написать выразительный и общий методenqueue
.fun<T> Call<T>.onEnqueue(actOnSuccess: (Response<T>) -> Unit, actOnFailure: (t: Throwable?) -> Unit) { this.enqueue(object: Callback<T> { override fun onFailure(call: Call<T>?, t: Throwable?) { actOnFailure(t) } override fun onResponse(call: Call<T>?, response: Response<T>) { actOnSuccess(response) } }) }
Это может быть использовано как:
request.onEnqueue { actOnSuccess = { doOnSuccess() } actOnFailure = { doOnFailure() } }
В блоках кода actOnSuccess и actOnFailure,
it
должны относиться к объектамResponse
иThrowable
соответственно, и могут быть использованы соответственно. Например, в блоке кода actOnFailure -actOnFailure = { doOnFailure() //it.message //'it' refers to the Throwable object. }