如何解决Android 通用 Gson.fromJson() 转换与协程和流程
我正在制作用于访问 otp api 的通用类。任何人都可以使用 otp 部分,只需要传递请求、响应类和 url,所有这些都将由这个 otp 部分完成。 请注意:这个响应类可以是不同的类型(例如:MobileOtpResponse,EmailOtpResponse)
下面是通用的 OtpClient,它接受任何请求类型并返回特定传递的 ResponseType(例如:传递的请求类是 OtpRequest ,传递的 ResponseType 类是 OtpResponse)
interface OtpClient {
@POST
suspend fun <Request : Any,ResponseType> sendOtp(@Url url: String,@Body request:@JvmSuppressWildcards Any): @JvmSuppressWildcards ResponseType
}
OtpRequest
data class OtpRequest(@Serializedname("mobile_number") val mobileNumber: String,@Serializedname("app_version") val appVersion: String)
OtpResponse
data class OtpResponse(@Serializedname("status") val status: String = "",@Serializedname("response") val response: OtpData? = null)
data class OtpData(
@Serializedname("otp_status") val otpStatus: Boolean = false,@Serializedname("message") val message: String = "",@Serializedname("error") val error: Int? = null,@Serializedname("otp_length") val otpLength: Int? = null,@Serializedname("retry_left") val retryLeft: Int? = null,)
现在我创建 Repo 来调用这个 api 这只是使用流,当数据获取时它发出数据
class OtpRepoImpl<out Client : OtpClient>(val client: Client) :OtpRepo {
override fun <Request:Any,ResponseType> sentOtpApi(url: String,request: Request): Flow<ResponseType> {
return flow<ResponseType> {
// exectute API call and map to UI object
val otpResponse = client.sendOtp<Request,ResponseType>(url,request)
emit(otpResponse)
}.flowOn(dispatchers.IO) // Use the IO thread for this Flow
}
}
这个 repo 用于 viewmodel 类
@ExperimentalCoroutinesApi
fun <A : Class<ResponseType>,Request : Any,ResponseType : Any> sendOtp(a: Class<ResponseType>,request: Request,response: ResponseType,url: String) {
viewmodelScope.launch {
repo.sentOtpApi<Request,request = request)
.onStart { _uiState.value = OtpState.Loading(true) }
.catch { cause ->
_uiState.value = OtpState.Loading(false)
getResponseFromError<Class<ResponseType>,ResponseType>(cause,response) {
// emit(it)
}
}
.collect {
_uiState.value = OtpState.Loading(false)
_uiState.value = OtpState.Success(it)
}
}
}
正如你在上面看到的,这个 sendOtp 方法是从视图类调用的,在这个方法中,我们使用 repo.sentOtpApi 并传递通用请求响应类型。我在 catch 块中获取数据,因为 api 在 400 HttpException 中发送错误 otp 数据,所以我创建了另一个方法 getResponseFromError 来获取错误响应,它应该解析 errorBody 响应并调用这个 lambda 块。
private suspend fun <A : Class<*>,ResponseType : Any> getResponseFromError( cause: Throwable,rp: ResponseType,block: suspend (ResponseType) -> Unit) {
if (cause is HttpException) {
val response = cause.response()
if (response?.code() == 400) {
println("fetching error Response")
val errorResponse = response.errorBody()?.charStream()
val turnsType = object : Typetoken<ResponseType>() {}.type
val finalErrorResponse = Gson().fromJson<ResponseType>(errorResponse,turnsType)
block(finalErrorResponse)
} else {
println("someOther exception")
}
} else
_uiState.value = OtpState.Error(cause)
}
val turnsType = object : Typetoken<ResponseType>() {}.type
val finalErrorResponse = Gson().fromJson<ResponseType>(errorResponse,turnsType)
block(finalErrorResponse)
此 finalErrorResponse 返回 LinkedTreeMap 而不是 ResponseType(在本例中为 OtpResponse) 我也试过使用 Class 这样的类型
val turnsType = object : Typetoken<A>() {}.type
val finalErrorResponse = Gson().fromJson<A>(errorResponse,turnsType)
但它不起作用。
var classtype = OtpResponse::class.java
otpviewmodel.sendOtp(a = classtype,request = otpRequest,response = OtpResponse(),url =
"http://preprod-api.nykaa.com/user/otp/v2/send-wallet-otp")
[![finalErroResponse 中的值][1]][1] [1]:https://i.stack.imgur.com/Holui.png
必需:finalErroResponse 应该是 OtpResponse 类型,因为它是在 sentOtp func 中传递的
请帮忙:)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。