retrofit2 + 协程封装

package com.base.common

import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit

object RetrofitClient {
    private const val BASE_URL = "https://api.apiopen.top/"
    private val httpInterceptor: HttpInterceptor = HttpInterceptor()
    private val okHttpClient = OkHttpClient.Builder()
        .callTimeout(30, TimeUnit.SECONDS).addInterceptor(httpInterceptor)
        .cache(
            CacheHelper.instance?.cache
        )
        .readTimeout(15, TimeUnit.SECONDS)
        .writeTimeout(15, TimeUnit.SECONDS)
        .retryOnConnectionFailure(true)
        .build()
    private val retrofit = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .client(okHttpClient)
        .build()

    fun <T> create(serviceClass: Class<T>): T = retrofit.create(serviceClass)
}
import retrofit2.http.*
import com.test.login.UserBean as UserBean

interface ApiStore {
    // https://blog.csdn.net/c__chao/article/details/78573737 测试接口来自地址
    @GET("getSingleJoke?")
    suspend fun login(@Query ("sid") sid:String): UserBean
}
class ApiService {
    companion object {
        private var TAG: String = "ApiService"
        private var apiService = RetrofitClient.create(ApiStore::class.java)
        suspend fun ktLogin(request: BaseRequestParams): UserBean {
            // 为了测试方便,使用测试接口这里传递的参数并非真正的请求参数
            //NetDataUtils.createJson(request)
            return apiService.login("28654780")
        }
    }

    private suspend fun <T : BaseBean?> Call<T>.await(): T {
        return suspendCancellableCoroutine { continuation ->
            enqueue(object : RetrofitCallBack<T>() {
                override fun success(data: T) {
                    continuation.resumeWith(runCatching {
                        data
                    })
                }

                override fun failed(data: T) {
                    if (continuation.isCancelled) return
                    continuation.resumeWith(runCatching {
                        data
                    })
                }
            })
            continuation.invokeOnCancellation {
                try {
                    cancel()
                } catch (ex: Throwable) {
                    Log.e(TAG, "ApiService continuation invokeOnCancellation cancel Throwable")
                }
            }
        }
    }
}

package com.base.common

import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.lang.reflect.ParameterizedType

 open class RetrofitCallBack<T : BaseBean ?>(private val callBack: CallBack<T>) : Callback<T> {
     override fun onResponse(call: Call<T>, response: Response<T>) = if (response.isSuccessful) {
         val body = response.body()
         // 网络请求成功返回的code值
         if (body?.code == ServiceCode.SUCCESS) {
             callBack.success(body)
         } else {
             // 接口调用返回错误码
             callBack.failed(createErrorData(body?.code,body?.message,create()))
         }
    } else {
        // 网络请求失败
        callBack.failed(createErrorData(response.code(),response.message(),create()))
    }

    override fun onFailure(call: Call<T>, t: Throwable) {
        // 网络请求异常
        callBack.failed(createErrorData(ServiceCode.HTTP_ERROR_CODE,t.message,create()))
    }

    private fun createErrorData(code:Int?, message:String?,data : T): T
    {
        data!!.message = message
        data.code = code
        return data
    }

    private fun <T> create(): T
    {
        var mClass: Class<T> =
            (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class<T>
        return mClass.newInstance()
    }
}

interface CallBack<T> {
     fun success(data: T)
     fun failed(data: T)
}
```kotlin
package com.base.common

open class BaseBean(
    var code: Int? = 0,
    var message: String? = null,
)
package com.test.login

import com.base.common.BaseBean

open class UserBean: BaseBean() {
    lateinit var result: ResultData
}

class ResultData(
    var sid: String,
    val text: String,
)

view module 调用方式

class UserModel : BaseViewModel() {
    val userBean: MutableLiveData<UserBean> by lazy {
        MutableLiveData<UserBean>()
    }

    fun getData() {
        //使用IO线程? Retrofit已经使用子线程方式,多一次线程切换,是否有必要?
        viewModelScope.launch(Dispatchers.IO) {
            var start = System.currentTimeMillis()
            val clz = LoginRequestParams::class.java
            val request = NetDataUtils.createRequest(clz)
            val userData = ApiService.ktLogin(request)
            var end = System.currentTimeMillis()
            Log.e("UserModel", "UserModel http time" + (end - start))
            // 收到请求的回调可以选择判断处理,然后发送通知给Activity
            userBean.postValue(userData)
        }
    }
}
package com.base.common

class ServiceCode {
    companion object {
         const val SUCCESS = 0
         const val HTTP_ERROR_CODE = Int.MAX_VALUE - 1
    }
}

可能用到的包

api "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
api "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
api (['com.squareup.okhttp3:logging-interceptor:3.9.0',
      'com.squareup.retrofit2:retrofit:2.7.2',
      'com.squareup.retrofit2:converter-gson:2.7.2')
api 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.3'
上一篇:@JSONField @JsonFormat @JsonProperty 使用场景


下一篇:SpringBoot 中进行参数校验