簡體   English   中英

為 Retrofit Kotlin 協程創建自定義網絡監聽器

[英]Creating custom network listner for Retrofit Kotlin Coroutine

我正在使用改裝服務而不使用回調。 因此,它可能與 Kotlin Coroutine suspend fun一起使用。 我參考了許多博客、媒體和許多教程。 好吧,使用協程scopeIO and Main線程很容易得到響應。

所以,在參考了一些例子之后,我考慮做這樣的代碼:

改造服務接口RetrofitInterfaces.kt

interface RetrofitInterfaces {
    @FormUrlEncoded
    @POST("get-videos-pagination")
    suspend fun getTemplates(@Field("app_name") app_name: String,
                             @Field("sort_by") sortBy: String,
                             @Field("video_loaded_ids") loadedIds: String): Response<Model_Video_List>
}

其中Model_Video_List.kt class 是我的響應數據 class。

Retrofit 生成器RetrofitClient.kt

object RetrofitClient {
    fun makeRetrofitService(mContext: Context): RetrofitInterfaces {
    val gson = GsonBuilder().setLenient().create()
    return Retrofit.Builder()
            .baseUrl(AppPreferences.getBaseUrl(mContext) + "/api/v3/")
            .addConverterFactory(GsonConverterFactory.create(gson))
            .build().create(RetrofitInterfaces::class.java)
}
}

在這里,我使用Gson serialisedeserialiseJson data

現在有什么問題以及問題從哪里開始得到錯誤響應我正在使用ResultWrapper.kt

class ResultWrapper {
    enum class ErrorCode {
        NETWORK,// Connection failed or timeout
        SERVER,// Server errors due to maintenance or over request
        INVALID// Response is success but can't serialised with Data Class!
    }

    interface ResponseWrapper {
        suspend fun onSuccess(response: Response<Any>)

        suspend fun onFailure(eCode: ErrorCode)
    }

    private var responseWrapper: ResponseWrapper? = null
        set

    suspend fun enqueue(response: Response<Any>, responseWrapper: ResponseWrapper) {
        this.responseWrapper = responseWrapper
        if (response.isSuccessful) {
            responseWrapper.onSuccess(response)
        } else {
            val errorCode = response.code()
            when (errorCode) {
                in 200..299 -> {
                    responseWrapper.onFailure(ErrorCode.INVALID)
                }
                in 400..499 -> {
                    responseWrapper.onFailure(ErrorCode.NETWORK)
                }
                in 500..599 -> {
                    responseWrapper.onFailure(ErrorCode.SERVER)
                }
            }
        }
    }
}

所以,現在我可以在app的任何地方調用這個enqueue fun ,比如:

private fun getVideoList(loadedIds: String, sortBy: String) {
    val service = RetrofitClient.makeRetrofitService(mContext)
    scope.launch {
        val response = service.getTemplates("MyApp", sortBy, loadedIds)
        val resultWrapper = ResultWrapper()
        resultWrapper.enqueue(response, object : ResultWrapper.ResponseWrapper {
            override suspend fun onSuccess(response: Response<Any>) {

            }

            override suspend fun onFailure(eCode: ResultWrapper.ErrorCode) {

            }
        })
    }
}

但是我在resultWrapper.enqueue()中傳遞response時遇到compile error ,因為在ResultWrapper.ResponseWrapper interface中,有一個用suspend fun onSuccess(response: Response<Any>)定義的方法。 所以,這里出現了類型轉換問題!

如果 Retrofit CallBack<T>可以處理任何類型的Model or Data classes並返回精確的類型。 像上面的服務需要Model_Video_List class 來響應,其他服務需要有自己的那該怎么辦呢? 是否有唯一的方法為每個服務使用單獨的 function? 還是只有在 Java 中才有可能?!

您可以在 class ResultWrapper中引入通用參數類型T ,因此每當您創建此 class 的實例時,您必須指定一個實際類型來代替T

將您的ResultWrapper更改為:

class ResultWrapper<T> {
    enum class ErrorCode {
        NETWORK,// Connection failed or timeout
        SERVER,// Server errors due to maintenance or over request
        INVALID// Response is success but can't serialised with Data Class!
    }

    interface ResponseWrapper<T> {
        suspend fun onSuccess(response: Response<T>)

        suspend fun onFailure(eCode: ErrorCode)
    }

    private var responseWrapper: ResponseWrapper<T>? = null
        set

    suspend fun enqueue(response: Response<T>, responseWrapper: ResponseWrapper<T>) {
        this.responseWrapper = responseWrapper
        if (response.isSuccessful) {
            responseWrapper.onSuccess(response)
        } else {
            val errorCode = response.code()
            when (errorCode) {
                in 200..299 -> {
                    responseWrapper.onFailure(ErrorCode.INVALID)
                }
                in 400..499 -> {
                    responseWrapper.onFailure(ErrorCode.NETWORK)
                }
                in 500..599 -> {
                    responseWrapper.onFailure(ErrorCode.SERVER)
                }
            }
        }
    }
}

並將您的方法更改為:

private fun getVideoList(loadedIds: String, sortBy: String) {
    val service = RetrofitClient.makeRetrofitService(mContext)
    scope.launch {
        val response = service.getTemplates("MyApp", sortBy, loadedIds)
        val resultWrapper = ResultWrapper<Model_Video_List>()
        resultWrapper.enqueue(response, object : ResultWrapper.ResponseWrapper<Model_Video_List> {
            override suspend fun onSuccess(response: Response<Model_Video_List>) {

            }

            override suspend fun onFailure(eCode: ResultWrapper.ErrorCode) {

            }
        })
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM