使用Kotlin和Android JetPack開發一款App
電影資訊App是一個純練手專案,使用了系統API28,全部是基於Androidx包下的。使用Kotlin語言開發,使用了Android JetPack中的LiveData、ViewModel以及Room。為了學習Kotlin和鞏固自定義View和ViewGroup,這個專案是儘量少應用依賴第三方庫。Api來自豆瓣電影,豆瓣電影Api目前是不公開的,小編是在簡書上看到有人公開了訪問豆瓣電影的Api的API_KEY,如果有侵犯,請聯絡刪除!
專案截圖
截圖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以及動畫;
- 支援視訊播放
看幾段程式碼,訪問網路的核心程式碼,設計到了蠻多的知識點,這是初始化Retrofit
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資料來源介面卡
.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轉為LiveData
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()方法中。

這是小編的公眾號