android retrofit+kotlin协程封装网络框架(无RxJava、无回调、无LiveData)
无RxJava、无回调、无LiveData的retrofit网络框架
·
先看成品使用:
lifecycleScope.launch {
/**
* case1:只需要响应正确的结果
*/
//LoadingDialog.show() 可以很方便的处理LoadingDialog的逻辑
val result1 = RepoWanAndroid().searchArticle("安卓")
//LoadingDialog.cancel()
if (result1.isSuccess) {
L.err(result1.data?.datas?.get(0)?.title)
}
/**
* case2:需要处理错误
*/
//LoadingDialog.show()
val result2 = RepoWanAndroid().searchArticle("安卓")
//LoadingDialog.cancel()
if (result1.isSuccess) {
L.err(result2.data?.datas?.get(0)?.author)
}else{
L.err("所有的错误都会走到这里,如果不需区分错误的类型,直接在这里处理错误即可")
//针对不同类型的错误进行处理
when (result1.errorType) {
BaseBean.ErrorType.NetworkError ->{}
BaseBean.ErrorType.ServerError ->{}
BaseBean.ErrorType.UnknownError ->{}
}
//针对错误码进行处理
when (result1.errorCode) {
404->{}
500->{}
}
}
}
协程的出现,让我们可以最大限度的解决掉回调的问题,使代码可以按照线性的思维去编写。
此方案最核心一点,就是在网络数据返回的时候,顺带处理了错误信息,避免使用try catch,也就是底部SuspendCall类里的逻辑。思路很简单,直接上代码吧。
class RepoWanAndroid {
private val api = ApiServiceManager.getService(ApiWanAndroid::class.java)
suspend fun searchArticle(keyword: String): BaseBean<ArticleSearchResultBean> {
//Repository的意义在于可以封装一些默认参数,比如自己第三方接口的key,或者自己uid等
return api.searchArticle(keyword)
}
}
interface ApiWanAndroid {
@POST("article/query/0/json")
@FormUrlEncoded
suspend fun searchArticle(@Field("k") keyword: String): BaseBean<ArticleSearchResultBean>
}
class ApiServiceManager private constructor() {
private val mRetrofit: Retrofit = Retrofit.Builder()
.client(OkHttpClientManager.getClient())
//String converter
//用于直接返回String类型,遇到第一个匹配的Converter将会终止匹配
.addConverterFactory(ScalarsConverterFactory.create())
//Json Converter
//用于返回Bean对象
.addConverterFactory(MoshiConverterFactory.create())
//handle returns
//处理返回结果,
.addCallAdapterFactory(SuspendCallAdapterFactory.create())
.baseUrl("https://www.wanandroid.com/")
.build()
// 获取对应的Service
fun <T> create(service: Class<T>?): T {
return mRetrofit.create(service)
}
companion object {
private fun getInstance(): ApiServiceManager {
return SingletonHolder.instance
}
fun <T> getService(service: Class<T>?): T {
return getInstance().create(service)
}
}
// 静态内部类 形式的单例
private object SingletonHolder {
val instance = ApiServiceManager()
}
}
class CommonParamsInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val request: Request = chain.request()
val builder: HttpUrl.Builder = request.url.newBuilder()
//添加公用参数
builder.addQueryParameter("time", System.currentTimeMillis().toString())
val newRequest: Request = request.newBuilder()
.url(builder.build())
.build()
L.err("http_data url:${newRequest.url}")
return chain.proceed(newRequest)
}
}
class OkHttpClientManager private constructor() {
private val okHttpClient: OkHttpClient
// 请求超时时间
private val DEFAULT_TIMEOUT: Long = 20
init {
val loggingInterceptor = HttpLoggingInterceptor { message -> //message是网络返回来的内容
System.err.println("http_data:${message}")
}
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY)
//手动创建一个OkHttpClient并设置超时时间
val httpClientBuilder = OkHttpClient.Builder()
okHttpClient = httpClientBuilder
.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.addInterceptor(CommonParamsInterceptor())
.addInterceptor(loggingInterceptor)
.build()
}
companion object {
fun getClient(): OkHttpClient {
return SingletonHolder.instance.okHttpClient
}
}
private object SingletonHolder {
val instance = OkHttpClientManager()
}
}
class SuspendCallAdapterFactory : CallAdapter.Factory() {
override fun get(
returnType: Type,
annotations: Array<Annotation>,
retrofit: Retrofit
): CallAdapter<*, *>? {
//第一个泛型就是BaseBean类,这种情况可能是api接口没有声明协程suspend符号,抛出异常提醒
if (getRawType(returnType) == BaseBean::class.java) {
throw IllegalArgumentException("Method must be declare suspend, please check function declaration at API interface")
}
//协程挂起函数默认返回值是Call<*>,如果不满足该条件,那么返回null让retrofit选择其他家伙来处理
if (Call::class.java != getRawType(returnType)) {
return null
}
//检查Call内部的泛型是否包含了其他泛型
check(returnType is ParameterizedType) {
"return type must be BaseBean<*> or BaseBean<out *> for Call<*> check"
}
//获取Call类包裹的第一个泛型
val responseType = getParameterUpperBound(0, returnType)
//Call类包裹的第一个泛型不是BaseBean类,那么返回null,让retrofit选择其他 CallAdapter.Factory
if (getRawType(responseType) != BaseBean::class.java) {
return null
}
//确保BaseBean内部包的泛型其还包裹另外一层泛型,比如 BaseBean<*>
check(responseType is ParameterizedType) { "return type must be BaseBean<*> or BaseBean<out *> for BaseBean<*> check" }
//获取BaseBean类包裹的第一个泛型
val callReturnType = getParameterUpperBound(0, returnType as ParameterizedType)
return SuspendCallAdapter<Any?>(callReturnType)
}
companion object {
fun create(): SuspendCallAdapterFactory {
return SuspendCallAdapterFactory()
}
}
}
class SuspendCallAdapter<R>(private val responseType: Type) : CallAdapter<R, SuspendCall<R>> {
/**
* 真正数据的类型,如Call<T> 中的 T,这个T会作为 Converter.Factory.responseConverter的第一个参数
*
* @return
</T> */
override fun responseType(): Type {
return responseType
}
override fun adapt(call: Call<R>): SuspendCall<R> {
return SuspendCall(call)
}
}
class SuspendCall<R>(var delegate: Call<R>) : Call<Any> {
override fun execute(): Response<Any> {
throw UnsupportedOperationException("CustomCall doesn't support execute")
}
override fun enqueue(callback: Callback<Any>) {
delegate.enqueue(object : Callback<R> {
override fun onResponse(call: Call<R>, response: Response<R>) {
val baseBean = response.body() as BaseBean<Any>
if (baseBean.data == null) {
onFailure(call, Exception("数据为空"))
return
}
baseBean.isSuccess = true
callback.onResponse(this@SuspendCall, Response.success(baseBean))
return
}
override fun onFailure(call: Call<R>, t: Throwable) {
val baseBean = BaseBean<Any>()
baseBean.isSuccess = false
baseBean.errorMsg = t.message
baseBean.errorCode = -1
if (t is UnknownHostException) {
//可以针对各种情况进行处理
baseBean.errorType = BaseBean.ErrorType.ServerError
}
callback.onResponse(this@SuspendCall, Response.success(baseBean))
}
})
}
override fun isExecuted(): Boolean {
return delegate.isExecuted
}
override fun cancel() {
delegate.cancel()
}
override fun isCanceled(): Boolean {
return delegate.isCanceled
}
override fun clone(): Call<Any> {
return SuspendCall(delegate)
}
override fun request(): Request {
return delegate.request()
}
override fun timeout(): Timeout {
return delegate.timeout()
}
}
更多推荐
所有评论(0)