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.device.DeviceServiceManager
|
||||||
import com.yuanxuan.rokid.network.http.ApiRepository
|
import com.yuanxuan.rokid.network.http.ApiRepository
|
||||||
import com.yuanxuan.rokid.network.http.ApiService
|
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.http.RetrofitClient
|
||||||
import com.yuanxuan.rokid.network.websocket.WebSocketManager
|
import com.yuanxuan.rokid.network.websocket.WebSocketManager
|
||||||
import kotlinx.coroutines.CoroutineScope
|
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