diff --git a/app/src/main/java/com/hippo/ehviewer/client/EhEngine.kt b/app/src/main/java/com/hippo/ehviewer/client/EhEngine.kt index f741f17d4..e4418f212 100644 --- a/app/src/main/java/com/hippo/ehviewer/client/EhEngine.kt +++ b/app/src/main/java/com/hippo/ehviewer/client/EhEngine.kt @@ -52,6 +52,7 @@ import com.hippo.ehviewer.dailycheck.showEventNotification import com.hippo.ehviewer.dailycheck.today import com.hippo.ehviewer.util.AppConfig import com.hippo.ehviewer.util.StatusCodeException +import com.hippo.ehviewer.util.isCronetSupported import io.ktor.utils.io.pool.DirectByteBufferPool import kotlinx.coroutines.CancellationException import kotlinx.coroutines.delay @@ -133,16 +134,31 @@ val httpContentPool = DirectByteBufferPool(16, 16384) suspend inline fun fetchCompat(url: String, referer: String? = null, crossinline parser: (ByteBuffer) -> T): T { val ret: T - cronetRequest(url, referer).execute { - val buffer = httpContentPool.borrow() - try { - awaitBodyFully { - buffer.put(it) + if (isCronetSupported) { + cronetRequest(url, referer).execute { + val buffer = httpContentPool.borrow() + try { + awaitBodyFully { + buffer.put(it) + } + buffer.flip() + ret = parser(buffer) + } finally { + httpContentPool.recycle(buffer) + } + } + } else { + ehRequest(url, referer).execute { + val buffer = httpContentPool.borrow() + try { + while (true) { + if (body.source().read(buffer) == -1) break + } + buffer.flip() + ret = parser(buffer) + } finally { + httpContentPool.recycle(buffer) } - buffer.flip() - ret = parser(buffer) - } finally { - httpContentPool.recycle(buffer) } } return ret diff --git a/app/src/main/java/com/hippo/ehviewer/client/EhRequestBuilder.kt b/app/src/main/java/com/hippo/ehviewer/client/EhRequestBuilder.kt index 5ac6b0019..c847b04cf 100644 --- a/app/src/main/java/com/hippo/ehviewer/client/EhRequestBuilder.kt +++ b/app/src/main/java/com/hippo/ehviewer/client/EhRequestBuilder.kt @@ -38,6 +38,8 @@ import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.Response import okhttp3.executeAsync import okio.BufferedSource +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract import kotlin.coroutines.resume import kotlin.coroutines.resumeWithException @@ -104,7 +106,12 @@ suspend inline fun Call.usingCancellable(crossinline block: suspend Response } } -suspend inline fun Request.execute(block: Response.() -> R) = okHttpClient.newCall(this).executeAsync().use(block) +suspend inline fun Request.execute(block: Response.() -> R): R { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return okHttpClient.newCall(this).executeAsync().use(block) +} suspend inline fun Request.executeNonCache(crossinline block: suspend Response.() -> R) = baseOkHttpClient.newCall(this).usingCancellable(block) suspend inline fun Request.executeNoRedirect(block: Response.() -> R) = noRedirectOkHttpClient.newCall(this).executeAsync().use(block)