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())
.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?")
fun login(@Query ("sid") sid:String): Call<BaseBean<UserBean>>
}
class ApiService {
companion object {
private var TAG: String = "ApiService"
private var apiService = RetrofitClient.create(ApiStore::class.java)
suspend fun ktLogin(request: BaseRequestParams): BaseBean<UserBean> {
// 为了测试方便,使用测试接口这里传递的参数并非真正的请求参数
//NetDataUtils.createJson(request)
return apiService.login("28654780").awaitCall()
}
suspend fun upFile(request: BaseRequestParams, requestListener: RequestListener): BaseBean<UserBean> {
//NetDataUtils.createJson(request)
var file = File(request.id.toString())
val requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file)
val fileRequestBody = FileRequestBody(requestBody, requestListener)
return apiService.uploadFile(fileRequestBody).awaitCall()
}
private suspend fun <T> Call<BaseBean<T>>.awaitCall(): BaseBean<T> {
return suspendCancellableCoroutine {
enqueue(object : RetrofitCallBack<T>() {
override fun success(data: BaseBean<T>) {
it.resumeWith(runCatching {
data
})
}
override fun failed(data: BaseBean<T>) {
it.resumeWith(runCatching {
data
})
}
})
it.invokeOnCancellation {
try {
cancel()
} catch (ex: Throwable) {
Log.e(TAG, "ApiService continuation invokeOnCancellation cancel Throwable")
}
}
}
}
}
}
package com.base.common
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
abstract class RetrofitCallBack<T> : Callback<BaseBean<T>> {
@Suppress("UNCHECKED_CAST")
override fun onResponse(call: Call<BaseBean<T>>, response: Response<BaseBean<T>>) {
if (response.isSuccessful) {
val body = response.body()
// 网络请求成功返回的code值
if (body?.code == ServiceCode.SUCCESS) {
success(body)
} else {
// 接口调用返回错误码
failed(
BaseBean(
body!!.code ?: ServiceCode.HTTP_ERROR_CODE,
body.message ?: "",
Any() as T
)
)
}
} else {
// 网络请求失败
failed(BaseBean(response.code(), response.message(), Any() as T))
}
}
@Suppress("UNCHECKED_CAST")
override fun onFailure(call: Call<BaseBean<T>>, t: Throwable) {
val errorBean = BaseBean(ServiceCode.HTTP_ERROR_CODE, t.message, Any() as T)
failed(errorBean)
}
abstract fun success(data: BaseBean<T>)
abstract fun failed(data: BaseBean<T>)
}
```kotlin
package com.base.common
open class BaseBean<T>(
var code: Int? = 0,
var message: String? = null,
var result: T
)
package com.test.login
import com.base.common.BaseBean
open class UserBean {
var sid: String? = null
var text: String? = null
}
view module 调用方式
class UserModel : BaseViewModel() {
val userBean: MutableLiveData<BaseBean<UserBean>> by lazy {
MutableLiveData<BaseBean<UserBean>>()
}
fun getData() {
viewModelScope.launch(Dispatchers.IO) {
var start = System.currentTimeMillis()
val clz = LoginRequestParams::class.java
val request = NetDataUtils.createRequest(clz)
// 收到请求的回调可以选择判断处理,然后发送通知给Activity
val userData = ApiService.ktLogin(request)
userBean.postValue(userData)
}
}
}
```kotlin
package com.base.common
class ServiceCode {
companion object {
const val SUCCESS = 200
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'