好久没写博客了,最近也是比较忙,新项目使用了协程和Retrofit2.6,开发过程中发现了Retrofit2.6上传文件不支持中文名称,排查发现是其Okhttp新版本不支持,只能降低Retorfit版本了,低版本的Retrofit也不支持协程了,需要自己封装一下,今天就记录一下封装方法以及使用。
添加项目依赖,新项目还用到了lifecycle
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'org.ligboy.retrofit2:converter-fastjson-android:2.1.0'
implementation 'com.squareup.retrofit2:converter-scalars:2.0.0'、
implementation "android.arch.lifecycle:extensions:1.1.1"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.5.1"
定义基础数据返回类
@NoArgOpenDataClass
data class BaseResp<T>(var code: Int=0, var description: String?, var data: T?){
}
为了能像RxJava那种链式展示,我自定义了用于请求的DSL样式
class HttpRequestDsl<T : BaseResp<*>>() {
//协程作用域
lateinit var scope: CoroutineScope
//请求响应
lateinit var response: Response<T?>
internal var onSuccess: ((T) -> Unit)? = null
internal var onComplete: (() -> Unit)? = null
internal var onError: ((Exception) -> Unit)? = null
fun onSuccess(onSuccess: ((T) -> Unit)?) {
this.onSuccess = onSuccess
}
fun onComplete(onComplete: (() -> Unit)) {
this.onComplete = onComplete
}
fun onError(onError: ((Exception) -> Unit)?) {
this.onError = onError
}
}
在顶层文件中定义一个通用的请求方法
fun <T : BaseResp<*>> requestApi(
scope: CoroutineScope,
request: suspend CoroutineScope.() -> Call<T?>,
dsl: HttpRequestDsl<T>.() -> Unit
): Job {
return scope.launch {
val httpRequestDsl = HttpRequestDsl<T>()
try {
httpRequestDsl.scope = scope
withContext(Dispatchers.IO) {
//dsl主要是对onSuccess、onComplete和onError赋值
httpRequestDsl.dsl()
//执行request区域方法,并赋值response
httpRequestDsl.response = request.invoke(scope).execute()
}
if (httpRequestDsl.response.isSuccessful) {
val body = httpRequestDsl.response.body()
if (body != null) {
httpRequestDsl.onSuccess?.invoke(body)
httpRequestDsl.onComplete?.invoke()
} else {
httpRequestDsl.onError?.invoke(HttpException(httpRequestDsl.response))
}
} else {
val httpException = HttpException(httpRequestDsl.response)
httpRequestDsl.onError?.invoke(httpException)
}
} catch (e: Exception) {
e.printStackTrace()
if (!(e is CancellationException)) {
httpRequestDsl.onError?.invoke(e)
}
}
}
}
扩展ViewModel类,添加一个requestApi方法
fun <T : BaseResp<*>> ViewModel.requestApi(
request: suspend CoroutineScope.() -> Call<T?>,
dsl: HttpRequestDsl<T>.() -> Unit
): Job {
return requestApi(this.viewModelScope, request, dsl)
}
工具简单封装好了,接下来就可以使用啦
定义一个请求接口类
interface UserPost {
@POST("/app/Login")
fun login(@Body body: RequestBody?): Call<BaseResp<LoginData>?>
}
在需要网络请求的地方使用
requestApi({
val request = LoginRequest()
RetrofitManager.instance.create<UserPost>().login(
instance.getRequestBodyByObject(request)
)
}, {
onSuccess {
……
}
onError {
……
}
onComplete {
……
}
})