问题描述
我正在尝试使用 Ktor 为我们的 ApiServices 构建 KMM 应用程序。我创建了一个 BaseApiClass
,其中包含所有与 API 相关的代码。
BaseApiClass
的代码:-
class BaseAPIClass {
//Create Http Client
private val httpClient by lazy {
HttpClient {
defaultRequest {
host = ApiEndPoints.Base.url
contentType(ContentType.Application.Json)
header(CONNECTION,CLOSE)
}
install(Logging) {
logger = Logger.DEFAULT
level = LogLevel.ALL
}
install(HttpTimeout) {
requestTimeoutMillis = NETWORK_REQUEST_TIMEOUT
}
expectSuccess = false
// JSON Deserializer
install(JsonFeature) {
val json = Json {
ignoreUnkNownKeys = true
coerceInputValues = true
}
serializer = KotlinxSerializer(json)
}
}
}
// Api Calling Functions I have few more similar to this but issue is random and comes in any of the api
@Throws(Exception::class)
suspend fun sampleApi(requestBody: RequestBody?) : Either<CustomException,BaseResponse<EmptyResponseModel>> {
return try {
val response = httpClient.post<BaseResponse<EmptyResponseModel>> {
url(ApiEndPoints.sample.url)
if (requestBody != null) {
body = requestBody
}
}
Success(response)
}
catch (e: Exception) {
Failure(e as CustomException)
}
}
val apiClass = BaseApiClass()
func callApi() {
apiClass.sampleApi(requestBody: .init(string: "value here")) { (result,error) in
result?.fold(Failed: { (error) -> Any? in
// Error here
},succeeded: { (result) -> Any? in
// Success here
})
}
}
现在,如果我尝试使用相同的 object
即 apiClass
调用类似的更多 api,那么在几次调用后它会卡在我的函数 callApi
中,它甚至不发送 api请求(因为我看不到控制台中打印的请求日志),因此我无法执行任何其他操作,因为我没有从 api 中获得任何东西。
只要我更换屏幕或关闭应用程序并尝试调用相同的 api,它就会运行良好。
但是,如果我尝试使用 apiClass = BaseApiClass()
,它不会像这样只在一次创建一个对象 BaseApiClass().sampleApi(request params here) {// completion handler here}
,它可以正常工作,我不会遇到任何问题。
我不确定是什么导致了这种情况的发生,在 Android
中一切正常,这仅适用于 iOS
。
解决方法
您在使用 Coroutines 库的多线程变体吗?官方文档指出在使用 Ktor 时应该使用此变体。见here
,经过所有努力并尝试了大量调试技巧后,我明白了共享模块中的完成处理程序永远不会被调用,即使我收到来自 api 的响应。
我实现的唯一解决方案是使用 expect
和 actual
机制创建不同的 HTTP 客户端。通过制作单独的客户端,我还没有遇到过这个问题。
如果您有任何其他答案或解决方案,我很乐意查看。
,尝试在 install(Logging) 块中设置 LogLevel.NONE。
目前我是这样解决的,因为好像是Ktor的一个bug。
请参阅:https://youtrack.jetbrains.com/issue/KTOR-2711
它应该在 1.6.0 版本中修复。