背景
- 最近看到很多項目都將RxJava + Retrofit 替換成了 Coroutine + retrofit,首先Coroutine學習成本相對於Rxjava來說較低,而且最重要的一點是Kotlin的下實現線程切換的代碼更加精簡,邏輯相對更加清晰一些
注意:沒有學習過DSL 以及 協程(此次實踐將會使用) 的可以閱讀以下兩篇
Kotlin DSL
Kotlin 協程
封裝RxJava + Retrofit + OkHttp3網絡請求框架
1.首先添加以下開源庫的依賴
"retrofit" : "com.squareup.retrofit2:retrofit:$retrofit_version",
"retrofit-converter-gson" : "com.squareup.retrofit2:converter-gson:${retrofit_version}",
"retrofit-adapter-rxjava2" : "com.squareup.retrofit2:adapter-rxjava2:${retrofit_version}",
"okhttp3" : "com.squareup.okhttp3:okhttp:${okhttp_version}",
"okhttp3-logging-interceptor": "com.squareup.okhttp3:logging-interceptor:${okhttp_version}",
"rxkotlin" : "io.reactivex.rxjava2:rxkotlin:$rx_kotlin_version",
"rxandroid" : "io.reactivex.rxjava2:rxandroid:$rx_android_version",
2.創建RetrofitFactory類
class RetrofitFactory private constructor() {
private val retrofit : Retrofit
fun <T> create(clazz: Class<T>) : T {
return retrofit.create(clazz)
}
init {
retrofit = Retrofit.Builder()
.baseUrl(Constant.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(initOkHttpClient())
.build()
}
companion object {
val instance by lazy {
RetrofitFactory()
}
}
private fun initOkHttpClient(): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor() // 添加自定義攔截器
.connectTimeout(30, TimeUnit.SECONDS) // 請求超時時間
.writeTimeout(30, TimeUnit.SECONDS) // 寫入超時時間
.readTimeout(30, TimeUnit.SECONDS) // 讀取超時時間
.build()
}
}
3.創建api接口類
/** @GET GET請求方式
@POST POST請求方式
@Query GET請求參數
@Header用來添加Header請求頭
@FormUrlEncoded post請求頭標示
其他註解請求方式:
@PUT 表示這是一個PUT請求
@DELETE 表示這是一個DELETE請求
@HEAD 表示這是一個HEAD請求
@OPTIONS 表示這是一個OPTION請求
@PATCH 表示這是一個PAT請求
**/
interface ApiService {
@GET("/banner/json")
fun loadBanner(): Observable<BaseResponse<List<BannerResponse>>>
}
4.創建倉庫類作爲統一封裝入口
class HomeRepository (loadState : MutableLiveData<State>) : ArticleRepository(loadState) {
fun loadBanner(liveData: MutableLiveData<BaseResponse<List<BannerResponse>>>) {
apiService.loadBanner()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
BaseObserver(
liveData,
loadState,
this
)
)
}
}
- BaseObserver是對返回結果的處理
5.在ViewModel中對數據進行管理
class HomeViewModel(application: Application) :
ArticleViewModel<HomeRepository>(application) {
val mBannerData: MutableLiveData<BaseResponse<List<BannerResponse>>> = MutableLiveData()
fun loadBanner() {
mRepository.loadBanner(mBannerData)
}
}
6.在Activity或者Fragment中對ViewModel中的數據進行觀察即可
封裝 Coroutine + Retrofit + OkHttp3網絡請求框架
1.改寫api接口類
// 使用suspend函數修飾
@GET("/banner/json")
suspend fun loadBannerCo() : BaseResponse<List<BannerResponse>>
2.使用DSL封裝數據解析類
- 不使用RxJava所以對返回的數據處理就不能使用BaseObserver
- 所以在repository中調用apiServer的方法後需要將返回的數據做狀態處理,爲了簡潔我使用DSL封裝dataConvert數據解析類
fun <T> BaseResponse<T>.dataConvert(
loadState: MutableLiveData<State>
) : T{
// 將BaseObserver中的數據處理做相應的比那花即可
}
3.修改倉庫類
// 沒有使用LiveData的postValue將數據傳出,所以採用返回值的形式返回數據
suspend fun loadBannerCo() : List<BannerResponse> {
return apiService.loadBannerCo().dataConvert(loadState)
}
4.修改ViewModel
// 作爲返回值的接收值,在Activity或者Fragment中觀察該值即可
var mBannerData: MutableLiveData<List<BannerResponse>> =
MutableLiveData()
fun loadBannerCo() {
// 開啓協程
viewModelScope.launch {
try{
// 切換IO線程做數據請求
val data = withContext(Dispatchers.IO) {
mRepository.loadBannerCo()
}
// 設置LiveData即可
mBannerData.value = data
} catch (e : Exception) {
e.printStackTrace()
}
}
}
- 之後在Activity或者Fragment中對數據進行展示即可