背景
- 最近看到很多项目都将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{
when (errorCode) {
...
}
}
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中对数据进行展示即可