android - 使用 Kotlin 处理改造回调
问题描述
也许这是一个非常简单的话题,但我找不到正确的答案。
这是交易,我正在使用这个逻辑来处理 API 到我当前的 android 项目中:
类 SampleApi
接口 ISampleApi
接口 SampleClient
类 GetUserData
现在我要迁移到 Kotlin,我无法将enqueue()
改造中的功能复制到我的 Api 类中。这是我的代码示例:
获取用户数据.java:
class GetUserData {
private void tryGetData() {
sampleApi.getSomeData(userId, new Callback<Data>() {
@Override
public void onResponse(final Call<Data> call, final Response<Data> response) {
......Do Something
}
@Override
public void onFailure(final Call<Data> call, final Throwable t) {
......Do Something
}
});
我正在使用一个接口来声明要在 API 类中实现的方法:
public interface ISampleApi {
void getSomeData(@NonNull String userId,
@NonNull Callback<Data> callback);
}
这是我的 API 类:
public class SampleApi implements ISampleApi {
............
@Override
public void getSomeData(@NonNull final String userId,
@NonNull final Callback<Data> callback) {
myClient.getSomeData(userId).enqueue(callback);
}
}
这是使用 Retrofit 的 MyClient:
public interface SampleClient {
@GET("user/data/{userId}")
Call<Data> getSomeData(@NonNull @Path("userId") String userId);
}
上面的所有代码都可以正常工作,这就是我在我的应用程序中使用的没有问题。
现在,这是转移到 Kotlin 时的问题,我尝试在 SampleApi 中创建入队回调,我需要将响应返回到创建回调的类,在 Kotlin 中应该是这样的:
fun getSomeData(userId: String, callback: CallBack<Data>) {
client?.getSomeData(userId).enqueue(callback)
}
但是当尝试这样做时,Android Studio 告诉我必须创建一个扩展函数,我创建了扩展函数,经过 Android Studio 的更多建议和一些研究,结果是这样的:
override fun getSomeData(@NonNull userId: String,
@NonNull callback: Callback<Data>) {//Neve using this callback
client?.getSomeData(userId).enqueue {
success = {
success -> Do Something
}
failure = {
failure -> Do Something
}
}
}
fun<T> Call<T>.enqueue(callback: BaseCallback<T>.() -> Unit) {
val callbackBk = BaseCallback<T>()
callback.invoke(callbackBk)
this.enqueue(callbackBk)
}
class BaseCallback<T>: Callback<T> {
var success: ((Response<T>) -> Unit)? = null
var failure: ((t: Throwable?) -> Unit)? = null
override fun onFailure(call: Call<T>, t: Throwable) {
failure?.invoke(t)
}
override fun onResponse(call: Call<T>, response: Response<T>) {
success?.invoke(response)
}
}
BaseCallback.kt
open class BaseCallback<T: Validatable>(): Callback<BaseResponseBody<T>> {
var success: ((T) -> Unit)? = null
var failure: ((networkingError: NetworkingError?) -> Unit)? = null
override fun onResponse(call: Call<BaseResponseBody<T>>, response: Response<BaseResponseBody<T>>) {
if (response?.code() != null
&& response.isSuccessful
&& response.body() != null
&& response.body().containsValidSuccess()) run {
onSuccessfulResponse(response.body().data!!)
} else if (response != null
&& response.isSuccessful
&& response.body() != null) {
onSuccessfulResponse()
} else {
onNonSessionErrorEncountered(networkingError)
}
}
override fun onFailure(call: Call<BaseResponseBody<T>>, throwable: Throwable) {
onNonSessionErrorEncountered(NetworkStateError(throwable))
}
@VisibleForTesting(otherwise = PROTECTED)
fun onSuccessfulResponse(responseValue: T) {
success?.invoke(responseValue)
}
@VisibleForTesting(otherwise = PROTECTED)
fun onSuccessfulResponse() {
// This method intentionally left blank.
}
fun onSessionErrorEncountered() {
// This method intentionally left blank.
}
@VisibleForTesting(otherwise = PROTECTED)
fun onNonSessionErrorEncountered(networkingError: NetworkingError) {
failure?.invoke(networkingError)
}
}
此代码在这里工作正常,我可以接收数据,但我需要在调用此端点的类中接收响应,因为我需要更改 UI。
我真的很感谢一些帮助,我已经坚持了一段时间,我需要解决这个问题才能继续使用该应用程序。
解决方案
将以下代码放入 AppRepository.kt 文件中
companion object {
fun getServiceDetails(map: Map<String, String>, callback: ApiCallback<ServiceDetailsDataClass.ServiceDetailsResponse>) {
val retrofit = ApiClient.retrofit
val callGet = retrofit?.create<ApiService.ServiceDetails>(ApiService.ServiceDetails::class.java)?.getServiceDetails(map, ApiConstants.API_KEY, ApiConstants.API_LANG)
callGet?.enqueue(object : Callback<ServiceDetailsDataClass.ServiceDetailsResponse> {
override fun onFailure(call: Call<ServiceDetailsDataClass.ServiceDetailsResponse>?, t: Throwable?) {
callback.onError(t.toString())
}
override fun onResponse(call: Call<ServiceDetailsDataClass.ServiceDetailsResponse>?, response: Response<ServiceDetailsDataClass.ServiceDetailsResponse>?) {
if (response?.isSuccessful!!) {
callback.onSuccess(response.body()!!)
} else {
setError(callback, response)
}
}
})
}
ApiCallBack.kt 接口文件有代码:
interface ApiCallback<T> {
fun onException(error: Throwable)
fun onError(error: String)
fun onSuccess(t: T)
}
ApiService.kt 文件有代码:
interface ApiService {
interface ServiceDetails {
@GET("api/path/here/")
fun getServiceDetails(@QueryMap map: Map<String, String>, @Header(ApiConstants.KEY_X_API) apiKey: String, @Header(ApiConstants.KEY_ACCEPT_LANGUAGE) language: String): Call<ServiceDetailsDataClass.ServiceDetailsResponse>
}
现在调用 api 使用:
AppRepository.getServiceDetails(map, object : ApiCallback<ServiceDetailsDataClass.ServiceDetailsResponse> {
override fun onException(error: Throwable) {
serviceDetailsResponse.value = error
}
override fun onError(error: String) {
serviceDetailsResponse.value = error
}
override fun onSuccess(t: ServiceDetailsDataClass.ServiceDetailsResponse) {
serviceDetailsResponse.value = t
}
})
希望它可以帮助你。
推荐阅读
- python - geoToH3 函数作为伪代码可用吗?
- c# - 如何使用 MyWebRequest 将图像从 c# 应用程序上传到服务器(php 文件)
- c# - rx.net 合并重置流
- javascript - intl-tel-input : 禁用 console.log 中显示的 IP 地址信息
- python-3.x - Python 3 相当于 HTMLParseError?
- ios - 如何查看从 xcodebuild 输出生成的日志?
- elasticsearch - 是否有可能在弹性搜索中获得数组的联合
- ftp - 使用 AT+QFTPNLST 在 M66 OpenCPU 上列出 FTP 文件名的问题
- vue.js - 无法从 nuxt 中的商店访问 vuex-orm $db 变量
- javascript - 将“this”对象分配给函数内的变量有什么用?