使用Retrofit方法更具表现力的方式

时间:2017-04-05 13:43:50

标签: android retrofit kotlin higher-order-functions

我想让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 -> })

我认为可以使用扩展和高阶函数以某种方式进行改进。有谁知道怎么做?

5 个答案:

答案 0 :(得分:23)

这就是我使用扩展功能和类的方式

fun<T> Call<T>.enqueue(callback: CallBackKt<T>.() -> Unit) {
    val callBackKt = CallBackKt<T>()
    callback.invoke(callBackKt)
    this.enqueue(callBackKt)
}

class CallBackKt<T>: Callback<T> {

    var onResponse: ((Response<T>) -> Unit)? = null
    var onFailure: ((t: Throwable?) -> Unit)? = null

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

    override fun onResponse(call: Call<T>, response: Response<T>) {
        onResponse?.invoke(response)
    }

}

然后您可以像这样使用它

request.enqueue {

    onResponse = {
        // do
    }

    onFailure = {
        // do
    }

}

答案 1 :(得分:15)

给出以下功能:

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)
    }
}

你可以像这样使用Retrofit:

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) }))

答案 2 :(得分:6)

你可以做的就是这个(这是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的解决方案:

根据thisCallBackWrapper如下所示:

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相同。

答案 3 :(得分:5)

我在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 应分别引用ResponseThrowable个对象,并可相应地加以利用。例如,在actOnFailure代码块中 -

actOnFailure = {
        doOnFailure()
        //it.message //'it' refers to the Throwable object.
    }

答案 4 :(得分:1)

您可以创建这样的扩展功能

inline fun <T> Call<T>.addEnqueue(
    crossinline onSuccess: (response: Response<T>) -> Unit = { response: Response<T> -> },
    crossinline onFail: (t: Throwable) -> Unit = { throwable: Throwable ->}
):Callback<T> {
    val callback = object : Callback<T> {
        override fun onFailure(call: Call<T>, t: Throwable) {
            onFail(t)
        }

        override fun onResponse(call: Call<T>, response: Response<T>) {
            onSuccess(response)
        }
    }
    enqueue(callback)
    return callback
}

并在您的活动或片段中像这样使用它

 service?.fetchUser()?.addEnqueue(
            onSuccess = {
                doOnSuccess(it)
            },
            onFail = {
                doOnFail(it)
            }
    )