feat: 网络
This commit is contained in:
parent
4327a8638c
commit
f8b5f3a395
|
|
@ -4,7 +4,6 @@ import android.app.Application
|
|||
import com.yuanxuan.rokid.device.DeviceServiceManager
|
||||
import com.yuanxuan.rokid.network.http.ApiRepository
|
||||
import com.yuanxuan.rokid.network.http.ApiService
|
||||
import com.yuanxuan.rokid.network.http.OkHttpManager
|
||||
import com.yuanxuan.rokid.network.http.RetrofitClient
|
||||
import com.yuanxuan.rokid.network.websocket.WebSocketManager
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
|
|
|||
|
|
@ -1,135 +0,0 @@
|
|||
package com.yuanxuan.rokid.network.http
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.yuanxuan.rokid.network.NetUtils
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.Call
|
||||
import okhttp3.Callback
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.Response
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import timber.log.Timber
|
||||
import java.io.IOException
|
||||
import java.lang.Exception
|
||||
import java.lang.reflect.Type
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.resumeWithException
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
class OkHttpManager {
|
||||
|
||||
private val soTimeoutMillis = 30.milliseconds
|
||||
private val gson by lazy {
|
||||
Gson()
|
||||
}
|
||||
|
||||
private val okhttpClient by lazy {
|
||||
val httpLoggingInterceptor by lazy {
|
||||
HttpLoggingInterceptor { message ->
|
||||
Timber.tag("OkHttp").d(message)
|
||||
}.apply {
|
||||
level = HttpLoggingInterceptor.Level.BODY
|
||||
}
|
||||
}
|
||||
OkHttpClient.Builder()
|
||||
.connectTimeout(soTimeoutMillis)
|
||||
.readTimeout(soTimeoutMillis)
|
||||
.addInterceptor(httpLoggingInterceptor)
|
||||
.build()
|
||||
}
|
||||
|
||||
suspend fun testApi(): Test {
|
||||
return makeRequest<Test>(
|
||||
path = "",
|
||||
method = "GET",
|
||||
)
|
||||
}
|
||||
|
||||
private suspend inline fun <reified T> makeRequest(
|
||||
path: String,
|
||||
method: String,
|
||||
jsonBody: String? = null,
|
||||
headers: Map<String, String> = emptyMap(),
|
||||
): T = withContext(Dispatchers.IO) {
|
||||
|
||||
val requestBody = jsonBody?.toRequestBody("application/json".toMediaTypeOrNull())
|
||||
val request = buildRequest(
|
||||
path = path,
|
||||
method = method,
|
||||
body = requestBody,
|
||||
headers = headers
|
||||
)
|
||||
try {
|
||||
val response = okhttpClient.newCall(request).executeAwait()
|
||||
val responseBody = response.body.string()
|
||||
//过滤http错误
|
||||
if (response.isSuccessful.not()) {
|
||||
throw NetworkException(
|
||||
message = "Http error: ${response.code} ${response.message}"
|
||||
)
|
||||
}
|
||||
val typeToken = object : TypeToken<ApiResponse<T>>() {}
|
||||
val typeOfT: Type = typeToken.type
|
||||
val apiResponse: ApiResponse<Test> = gson.fromJson(responseBody, typeOfT)
|
||||
if (apiResponse.isSuccess().not()) {
|
||||
throw NetworkException(
|
||||
message = "Business error: ${apiResponse.code} ${apiResponse.message}"
|
||||
)
|
||||
}
|
||||
return@withContext apiResponse.data as T
|
||||
} catch (e: Exception) {
|
||||
throw NetworkException("Http error: ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildRequest(
|
||||
path: String,
|
||||
method: String,
|
||||
body: RequestBody?,
|
||||
headers: Map<String, String>
|
||||
): Request {
|
||||
val request = Request.Builder()
|
||||
.url(NetUtils.getBaseUrl() + path)
|
||||
.method(method, body)
|
||||
headers.forEach { (key, value) ->
|
||||
request.addHeader(key, value)
|
||||
}
|
||||
return request.build()
|
||||
}
|
||||
|
||||
private suspend fun Call.executeAwait(): Response =
|
||||
suspendCancellableCoroutine { continuation ->
|
||||
enqueue(object : Callback {
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
if (continuation.context.isActive) {
|
||||
continuation.resumeWithException(e)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
//协程被取消忽略请求结果
|
||||
if (continuation.context.isActive) {
|
||||
continuation.resume(response)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
continuation.invokeOnCancellation {
|
||||
try {
|
||||
//协程被取消 终端网络请求
|
||||
cancel()
|
||||
} catch (_: Throwable) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue