mirror of
https://github.com/gedoor/legado.git
synced 2025-08-10 00:52:30 +00:00
Cronet共用okhttp的线程池
This commit is contained in:
@@ -2,7 +2,7 @@ package io.legado.app.help.http.cronet
|
||||
|
||||
import io.legado.app.help.http.okHttpClient
|
||||
import io.legado.app.utils.DebugLog
|
||||
import io.legado.app.utils.rethrowAsIOException
|
||||
import io.legado.app.utils.asIOException
|
||||
import okhttp3.*
|
||||
import okhttp3.EventListener
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
@@ -27,12 +27,24 @@ abstract class AbsCallBack(
|
||||
|
||||
var mResponse: Response
|
||||
|
||||
var mException: IOException? = null
|
||||
private var followCount = 0
|
||||
|
||||
|
||||
@Throws(IOException::class)
|
||||
abstract fun waitForDone(urlRequest: UrlRequest): Response
|
||||
|
||||
/**
|
||||
* 当发生错误时,通知子类终止阻塞抛出错误
|
||||
* @param error
|
||||
*/
|
||||
abstract fun onError(error: IOException)
|
||||
|
||||
/**
|
||||
* 请求成功后,通知子类结束阻塞,返回response
|
||||
* @param response
|
||||
*/
|
||||
abstract fun onSuccess(response: Response)
|
||||
|
||||
|
||||
override fun onRedirectReceived(
|
||||
request: UrlRequest,
|
||||
@@ -41,10 +53,13 @@ abstract class AbsCallBack(
|
||||
) {
|
||||
if (followCount > MAX_FOLLOW_COUNT) {
|
||||
request.cancel()
|
||||
mException = IOException("Too many redirect")
|
||||
onError(IOException("Too many redirect"))
|
||||
return
|
||||
}
|
||||
if (mCall.isCanceled()) {
|
||||
mException = IOException("Request Canceled")
|
||||
onError(IOException("Request Canceled"))
|
||||
request.cancel()
|
||||
return
|
||||
}
|
||||
followCount += 1
|
||||
val client = okHttpClient
|
||||
@@ -55,7 +70,7 @@ abstract class AbsCallBack(
|
||||
} else if (okHttpClient.followRedirects) {
|
||||
request.followRedirect()
|
||||
} else {
|
||||
mException = IOException("Too many redirect")
|
||||
onError(IOException("Too many redirect"))
|
||||
request.cancel()
|
||||
}
|
||||
}
|
||||
@@ -73,7 +88,7 @@ abstract class AbsCallBack(
|
||||
}
|
||||
|
||||
|
||||
@Throws(Exception::class)
|
||||
@Throws(IOException::class)
|
||||
override fun onReadCompleted(
|
||||
request: UrlRequest,
|
||||
info: UrlResponseInfo,
|
||||
@@ -83,7 +98,7 @@ abstract class AbsCallBack(
|
||||
|
||||
if (mCall.isCanceled()) {
|
||||
request.cancel()
|
||||
mException = IOException("Request Canceled")
|
||||
onError(IOException("Request Canceled"))
|
||||
}
|
||||
|
||||
byteBuffer.flip()
|
||||
@@ -91,9 +106,9 @@ abstract class AbsCallBack(
|
||||
try {
|
||||
buffer.write(byteBuffer)
|
||||
} catch (e: IOException) {
|
||||
DebugLog.i(javaClass.name, "IOException during ByteBuffer read. Details: ", e)
|
||||
mException = IOException("IOException during ByteBuffer read. Details:", e)
|
||||
throw e
|
||||
DebugLog.e(javaClass.name, "IOException during ByteBuffer read. Details: ", e)
|
||||
onError(IOException("IOException during ByteBuffer read. Details:", e))
|
||||
return
|
||||
}
|
||||
byteBuffer.clear()
|
||||
request.read(byteBuffer)
|
||||
@@ -108,7 +123,8 @@ abstract class AbsCallBack(
|
||||
buffer.asResponseBody(contentType)
|
||||
val newRequest = originalRequest.newBuilder().url(info.url).build()
|
||||
this.mResponse = this.mResponse.newBuilder().body(responseBody).request(newRequest).build()
|
||||
DebugLog.i(javaClass.simpleName, "end[${info.negotiatedProtocol}]${info.url}")
|
||||
onSuccess(this.mResponse)
|
||||
//DebugLog.i(javaClass.simpleName, "end[${info.negotiatedProtocol}]${info.url}")
|
||||
|
||||
eventListener?.callEnd(mCall)
|
||||
if (responseCallback != null) {
|
||||
@@ -123,8 +139,8 @@ abstract class AbsCallBack(
|
||||
|
||||
//UrlResponseInfo可能为null
|
||||
override fun onFailed(request: UrlRequest, info: UrlResponseInfo?, error: CronetException) {
|
||||
DebugLog.i(javaClass.name, error.message.toString())
|
||||
mException = error.rethrowAsIOException()
|
||||
DebugLog.e(javaClass.name, error.message.toString())
|
||||
onError(error.asIOException())
|
||||
this.eventListener?.callFailed(mCall, error)
|
||||
responseCallback?.onFailure(mCall, error)
|
||||
}
|
||||
@@ -132,7 +148,7 @@ abstract class AbsCallBack(
|
||||
override fun onCanceled(request: UrlRequest?, info: UrlResponseInfo?) {
|
||||
super.onCanceled(request, info)
|
||||
this.eventListener?.callEnd(mCall)
|
||||
mException = IOException("Cronet Request Canceled")
|
||||
onError(IOException("Cronet Request Canceled"))
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.legado.app.help.http.cronet
|
||||
|
||||
import io.legado.app.constant.AppLog
|
||||
import io.legado.app.help.config.AppConfig
|
||||
import io.legado.app.help.http.okHttpClient
|
||||
import io.legado.app.utils.DebugLog
|
||||
import okhttp3.Headers
|
||||
import okhttp3.MediaType
|
||||
@@ -13,11 +14,8 @@ import org.chromium.net.UploadDataProviders
|
||||
import org.chromium.net.UrlRequest
|
||||
import splitties.init.appCtx
|
||||
|
||||
import java.util.concurrent.ExecutorService
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
|
||||
val executor: ExecutorService by lazy { Executors.newCachedThreadPool() }
|
||||
//val executor: ExecutorService by lazy { Executors.newCachedThreadPool() }
|
||||
|
||||
val cronetEngine: ExperimentalCronetEngine? by lazy {
|
||||
if (!AppConfig.isGooglePlay) {
|
||||
@@ -48,7 +46,11 @@ fun buildRequest(request: Request, callback: UrlRequest.Callback): UrlRequest? {
|
||||
val url = request.url.toString()
|
||||
val headers: Headers = request.headers
|
||||
val requestBody = request.body
|
||||
return cronetEngine?.newUrlRequestBuilder(url, callback, executor)?.apply {
|
||||
return cronetEngine?.newUrlRequestBuilder(
|
||||
url,
|
||||
callback,
|
||||
okHttpClient.dispatcher.executorService
|
||||
)?.apply {
|
||||
setHttpMethod(request.method)//设置
|
||||
allowDirectExecutor()
|
||||
headers.forEachIndexed { index, _ ->
|
||||
@@ -65,7 +67,7 @@ fun buildRequest(request: Request, callback: UrlRequest.Callback): UrlRequest? {
|
||||
requestBody.writeTo(buffer)
|
||||
setUploadDataProvider(
|
||||
UploadDataProviders.create(buffer.readByteArray()),
|
||||
executor
|
||||
okHttpClient.dispatcher.executorService
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
@@ -49,7 +49,6 @@ class CronetInterceptor(private val cookieJar: CookieJar?) : Interceptor {
|
||||
OldCallback(request, call)
|
||||
}
|
||||
buildRequest(request, callBack)?.let {
|
||||
it.start()
|
||||
return callBack.waitForDone(it)
|
||||
}
|
||||
return null
|
||||
|
||||
@@ -268,7 +268,8 @@ object CronetLoader : CronetEngine.Builder.LibraryLoader() {
|
||||
return
|
||||
}
|
||||
download = true
|
||||
executor.execute {
|
||||
|
||||
Coroutine.async {
|
||||
val result = downloadFileIfNotExist(url, downloadTempFile)
|
||||
DebugLog.d(javaClass.simpleName, "download result:$result")
|
||||
//文件md5再次校验
|
||||
@@ -279,7 +280,7 @@ object CronetLoader : CronetEngine.Builder.LibraryLoader() {
|
||||
downloadTempFile.deleteOnExit()
|
||||
}
|
||||
download = false
|
||||
return@execute
|
||||
return@async
|
||||
}
|
||||
DebugLog.d(javaClass.simpleName, "download success, copy to $destSuccessFile")
|
||||
//下载成功拷贝文件
|
||||
@@ -289,6 +290,9 @@ object CronetLoader : CronetEngine.Builder.LibraryLoader() {
|
||||
@Suppress("SameParameterValue")
|
||||
deleteHistoryFile(parentFile!!, null)
|
||||
}
|
||||
// executor.execute {
|
||||
//
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,11 +6,8 @@ import androidx.annotation.RequiresApi
|
||||
import okhttp3.Call
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.chromium.net.CronetException
|
||||
import org.chromium.net.UrlRequest
|
||||
import org.chromium.net.UrlResponseInfo
|
||||
import java.io.IOException
|
||||
import java.nio.ByteBuffer
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
@@ -21,45 +18,29 @@ class NewCallBack(originalRequest: Request, mCall: Call) : AbsCallBack(originalR
|
||||
|
||||
@Throws(IOException::class)
|
||||
override fun waitForDone(urlRequest: UrlRequest): Response {
|
||||
return responseFuture.get(mCall.timeout().timeoutNanos(), TimeUnit.NANOSECONDS)
|
||||
}
|
||||
|
||||
override fun onRedirectReceived(
|
||||
request: UrlRequest,
|
||||
info: UrlResponseInfo,
|
||||
newLocationUrl: String
|
||||
) {
|
||||
super.onRedirectReceived(request, info, newLocationUrl)
|
||||
if (mException != null) {
|
||||
responseFuture.completeExceptionally(mException)
|
||||
urlRequest.start()
|
||||
return if (mCall.timeout().timeoutNanos() > 0) {
|
||||
responseFuture.get(mCall.timeout().timeoutNanos(), TimeUnit.NANOSECONDS)
|
||||
} else {
|
||||
return responseFuture.get()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
override fun onReadCompleted(
|
||||
request: UrlRequest,
|
||||
info: UrlResponseInfo,
|
||||
byteBuffer: ByteBuffer
|
||||
) {
|
||||
super.onReadCompleted(request, info, byteBuffer)
|
||||
if (mException != null) {
|
||||
responseFuture.completeExceptionally(mException)
|
||||
}
|
||||
/**
|
||||
* 当发生错误时,通知子类终止阻塞抛出错误
|
||||
* @param error
|
||||
*/
|
||||
override fun onError(error: IOException) {
|
||||
responseFuture.completeExceptionally(error)
|
||||
}
|
||||
|
||||
override fun onSucceeded(request: UrlRequest, info: UrlResponseInfo) {
|
||||
super.onSucceeded(request, info)
|
||||
responseFuture.complete(mResponse)
|
||||
}
|
||||
|
||||
override fun onFailed(request: UrlRequest, info: UrlResponseInfo?, error: CronetException) {
|
||||
super.onFailed(request, info, error)
|
||||
responseFuture.completeExceptionally(mException)
|
||||
}
|
||||
|
||||
override fun onCanceled(request: UrlRequest?, info: UrlResponseInfo?) {
|
||||
super.onCanceled(request, info)
|
||||
responseFuture.completeExceptionally(mException)
|
||||
/**
|
||||
* 请求成功后,通知子类结束阻塞,返回response
|
||||
* @param response
|
||||
*/
|
||||
override fun onSuccess(response: Response) {
|
||||
responseFuture.complete(response)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,20 +4,19 @@ import android.os.ConditionVariable
|
||||
import okhttp3.Call
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.chromium.net.CronetException
|
||||
import org.chromium.net.UrlRequest
|
||||
import org.chromium.net.UrlResponseInfo
|
||||
import java.io.IOException
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
class OldCallback(originalRequest: Request, mCall: Call) : AbsCallBack(originalRequest, mCall) {
|
||||
|
||||
private val mResponseCondition = ConditionVariable()
|
||||
private var mException: IOException? = null
|
||||
|
||||
@Throws(IOException::class)
|
||||
override fun waitForDone(urlRequest: UrlRequest): Response {
|
||||
//获取okhttp call的完整请求的超时时间
|
||||
val timeOutMs: Long = mCall.timeout().timeoutNanos() / 1000000
|
||||
urlRequest.start()
|
||||
if (timeOutMs > 0) {
|
||||
mResponseCondition.block(timeOutMs)
|
||||
} else {
|
||||
@@ -32,35 +31,25 @@ class OldCallback(originalRequest: Request, mCall: Call) : AbsCallBack(originalR
|
||||
if (mException != null) {
|
||||
throw mException as IOException
|
||||
}
|
||||
return this.mResponse
|
||||
return mResponse
|
||||
}
|
||||
|
||||
|
||||
override fun onReadCompleted(
|
||||
request: UrlRequest,
|
||||
info: UrlResponseInfo,
|
||||
byteBuffer: ByteBuffer
|
||||
) {
|
||||
super.onReadCompleted(request, info, byteBuffer)
|
||||
if (mException != null) {
|
||||
mResponseCondition.open()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSucceeded(request: UrlRequest, info: UrlResponseInfo) {
|
||||
super.onSucceeded(request, info)
|
||||
/**
|
||||
* 当发生错误时,通知子类终止阻塞抛出错误
|
||||
* @param error
|
||||
*/
|
||||
override fun onError(error: IOException) {
|
||||
mException = error
|
||||
mResponseCondition.open()
|
||||
}
|
||||
|
||||
override fun onFailed(request: UrlRequest, info: UrlResponseInfo?, error: CronetException) {
|
||||
super.onFailed(request, info, error)
|
||||
/**
|
||||
* 请求成功后,通知子类结束阻塞,返回response
|
||||
* @param response
|
||||
*/
|
||||
override fun onSuccess(response: Response) {
|
||||
mResponseCondition.open()
|
||||
}
|
||||
|
||||
|
||||
override fun onCanceled(request: UrlRequest?, info: UrlResponseInfo?) {
|
||||
super.onCanceled(request, info)
|
||||
mResponseCondition.open()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,8 +12,8 @@ val Throwable.msg: String
|
||||
}
|
||||
}
|
||||
|
||||
fun Throwable.rethrowAsIOException(): IOException {
|
||||
fun Throwable.asIOException(): IOException {
|
||||
val newException = IOException(this.message)
|
||||
newException.initCause(this)
|
||||
throw newException
|
||||
return newException
|
||||
}
|
||||
Reference in New Issue
Block a user