问题描述
我正在制作用于访问 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 (将#修改为@)