Retrofit完美適配LiveData,使用Kotlin和Android JetPack開發一款App

項目簡介

電影資訊App是一個純練手項目,使用了系統API28,所有是基於Androidx包下的。使用Kotlin語言開發,使用了Android JetPack中的LiveData、ViewModel以及Room。爲了學習Kotlin和鞏固自定義View和ViewGroup,這個項目是儘可能少應用依賴第三方庫。Api來自豆瓣電影,豆瓣電影Api目前是不公開的,小編是在簡書上看到有人公開了訪問豆瓣電影的Api的API_KEY,若是有侵犯,請聯繫刪除!java

項目截圖

截圖1 截圖2 截圖 3 截圖 4 截圖5
5.jpg
3.jpg
1.jpg
4.jpg
6.jpg

app主要設計到知識點:

  • Material Design UI設計風格;
  • 使用Kotlin開發,你們想學習和鞏固Kotlin,能夠參考這個App;
  • Retrofit適配LiveData手寫一個LiveDataCallAdapter適配器;
  • RecyclerView支持上拉刷新和下拉加載,而且能夠添加不一樣類型頭部和底部的View以及動畫;
  • 支持視頻播放

看幾段代碼,訪問網絡的核心代碼,設計到了蠻多的知識點,這是初始化Retrofitgit

class RetrofitClient {
    companion object {
        val serviceApi: ServiceApi by lazy {
            val retrofitClient = Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .client(OkHttpClient.Builder()
                            .addInterceptor(HttpLoggingInterceptor(HttpLoggingInterceptor.Logger { message ->
                                Log.i(TAG, message)
                            }).setLevel(HttpLoggingInterceptor.Level.BODY)
                            ).build())
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(LiveDataCallAdapterFactory())
                    .build()
            retrofitClient.create(ServiceApi::class.java)
        }
    }
}
複製代碼

注意這段代碼,經過工廠模式添加一個LiveData數據源適配器github

.addCallAdapterFactory(LiveDataCallAdapterFactory())
複製代碼

經過方法工廠返回LiveDataCallAdapter的實例,而且獲取泛型的參數類型網絡

class LiveDataCallAdapterFactory : Factory() {
    override fun get(returnType: Type, annotations: Array<Annotation>, retrofit: Retrofit): CallAdapter<*, *>? {
        val responseType: Type

        if (Factory.getRawType(returnType) != LiveData::class.java) {
            throw IllegalStateException("return type must be parameterized")
        }
        val observableType = Factory.getParameterUpperBound(0, returnType as ParameterizedType)
        val rawObservableType = Factory.getRawType(observableType)
        responseType = if (rawObservableType == Response::class.java) {
            if (observableType !is ParameterizedType) {
                throw IllegalArgumentException("Response must be parameterized")
            }
            Factory.getParameterUpperBound(0, observableType)
        } else {
            observableType
        }
        return LiveDataCallAdapter<Any>(responseType)
    }
}
複製代碼

注意adapt()方法中的代碼,經過適配器模式將Call轉爲LiveDataapp

class LiveDataCallAdapter<R>(private val responseType: Type) :
        CallAdapter<R, LiveData<R>> {
​
    override fun responseType() = responseType
​
    override fun adapt(call: Call<R>): LiveData<R> {
        return object : LiveData<R>() {
            private var started = AtomicBoolean(false)
            override fun onActive() {
                super.onActive()
                if (started.compareAndSet(false, true)) {
                    call.enqueue(object : Callback<R> {
                        override fun onResponse(call: Call<R>, response: Response<R>) {
                            postValue(response.body())
                        }
​
                        override fun onFailure(call: Call<R>, throwable: Throwable) {
                            postValue(null)
                        }
                    })
                }
            }
        }
    }
}
複製代碼

你們可能看這些代碼會比較懵,我是看了RxJava2中的RxJava2CallAdapterFactory中的代碼,之前只是會寫,可是點擊去看源碼,在分析就不同了。Observable在這至關於LiveData(被觀察者)。經過調用retrofitClient.create(ServiceApi::class.java),最終會調用到adapt()方法中。ide

github傳送門post

相關文章
相關標籤/搜索