Retrofit與LiveData結合

94me發表於2018-07-19

Retrofit與LiveData結合

寫上題目有點不知道怎麼寫了的很短暫的尷尬

有個問題,為什麼我們可以直接更改service介面方法的返回值。

先解釋一波,相信我們都對Rxjava+Retrofit使用很熟悉了吧,回憶一下步驟

  • 新增了Retrofit對Rxjava支援的依賴

    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
    複製程式碼
  • 在構建Retrofit例項的時候新增了RxJavaCallAdapterFactory

    addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    複製程式碼
  • 然後好像就可以直接更改介面方法的返回值進行使用了

    @POST("test")
    fun test():LiveData<Object>
    複製程式碼

這個CallAdapterFactory是什麼,為什麼能夠達到更改返回值進行使用

熟悉Retrofit原始碼或者瞭解過的人就知道CallAdapter是Retrofit的請求介面卡,CallAdapterFactory用於獲取CallAdapter例項,然後呼叫了CallAdapter的adapt方法返回你想要適配的返回值,就可以達到我們直接修改返回值進行使用的效果了

補充一句,Retrofit真的設計的美

好的開始我的表演

LiveDataCallAdapterFactory

直接貼上程式碼

class LiveDataCallAdapterFactory : CallAdapter.Factory() {
    /**
     * 如果你要返回
     * LiveData<?>
     */
    override fun get(returnType: Type?, annotations: Array<out Annotation>?, retrofit: Retrofit?): CallAdapter<*, *>? {
        if(returnType !is ParameterizedType){
            throw IllegalArgumentException("返回值需為引數化型別")
        }
        //獲取returnType的class型別
        val returnClass = CallAdapter.Factory.getRawType(returnType)
        if(returnClass != LiveData::class.java){
            throw IllegalArgumentException("返回值不是LiveData型別")
        }
        //先解釋一下getParameterUpperBound
        //官方例子
        //For example, index 1 of {@code Map<String, ? extends Runnable>} returns {@code Runnable}.
        //獲取的是Map<String,? extends Runnable>引數列表中index序列號的引數型別,即0為String,1為Runnable
        //這裡的0就是LiveData<?>中?的序列號,因為只有一個引數
        //其實這個就是我們請求返回的實體
        val type = CallAdapter.Factory.getParameterUpperBound(0, returnType as ParameterizedType)
        return LiveDataCallAdapter<Any>(type)
    }
    /**
     * 請求介面卡
     */
    class LiveDataCallAdapter<R>(var type:Type):CallAdapter<R,LiveData<R>>{
        override fun adapt(call: Call<R>?): LiveData<R> {
            return object:LiveData<R>(){
            	//這個作用是業務在多執行緒中,業務處理的執行緒安全問題,確保單一執行緒作業
                val flag = AtomicBoolean(false)
                override fun onActive() {
                    super.onActive()
                    if(flag.compareAndSet(false,true)){
                        call!!.enqueue(object: Callback<R> {
                            override fun onFailure(call: Call<R>?, t: Throwable?) {
                                postValue(null)
                            }
                            override fun onResponse(call: Call<R>?, response: Response<R>?) {
                                postValue(response?.body())
                            }
                        })
                    }
                }
            }
        }
        override fun responseType(): Type {
            return type
        }
    }
}
複製程式碼

註釋都在程式碼中,相信大家都能明白的

自定義CallAdapterFactory完了就可以在構建Retrofit例項的時候新增該Factory了,就可以使用

建議大家都嘗試自己自定義一個,沒有看過Retrofit原始碼的也該看了

其實有幾個小知識點

第一個 什麼是ParameterizedType

第二個 AtomicBoolean的作用

也可以參照一下官方的例子android-architecture-components

LiveDataCallAdapterFactory連結走你

寫程式碼要知道原理,總不能老是複製貼上拿來主義吧

相關文章