From 4cf51ac940ded4d8a937da2462f1d7fc60aa0593 Mon Sep 17 00:00:00 2001 From: Administrator <1760316362@qq.com> Date: Fri, 9 Aug 2019 13:20:24 +0800 Subject: [PATCH] update --- .../io/legado/app/data/api/CommonHttpApi.kt | 18 --- .../io/legado/app/data/api/IHttpGetApi.kt | 13 -- .../io/legado/app/data/api/IHttpPostApi.kt | 14 -- .../io/legado/app/help/coroutine/Coroutine.kt | 131 +++++++++++------- .../app/model/analyzeRule/AnalyzeUrl.kt | 17 --- .../app/model/webbook/BookChapterList.kt | 2 +- .../legado/app/model/webbook/BookContent.kt | 2 +- .../legado/app/ui/search/SearchViewModel.kt | 16 ++- 8 files changed, 90 insertions(+), 123 deletions(-) delete mode 100644 app/src/main/java/io/legado/app/data/api/CommonHttpApi.kt diff --git a/app/src/main/java/io/legado/app/data/api/CommonHttpApi.kt b/app/src/main/java/io/legado/app/data/api/CommonHttpApi.kt deleted file mode 100644 index 0819b3281..000000000 --- a/app/src/main/java/io/legado/app/data/api/CommonHttpApi.kt +++ /dev/null @@ -1,18 +0,0 @@ -package io.legado.app.data.api - -import kotlinx.coroutines.Deferred -import retrofit2.http.* - -interface CommonHttpApi { - - @GET - fun get(@Url url: String, @QueryMap map: Map): Deferred - - @FormUrlEncoded - @POST - fun post(@Url url: String, @FieldMap map: Map): Deferred - - - @GET - fun get(@Url url: String) : Deferred -} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/data/api/IHttpGetApi.kt b/app/src/main/java/io/legado/app/data/api/IHttpGetApi.kt index e4180fa59..774cf6c89 100644 --- a/app/src/main/java/io/legado/app/data/api/IHttpGetApi.kt +++ b/app/src/main/java/io/legado/app/data/api/IHttpGetApi.kt @@ -1,7 +1,6 @@ package io.legado.app.data.api import kotlinx.coroutines.Deferred -import retrofit2.Call import retrofit2.Response import retrofit2.http.GET import retrofit2.http.HeaderMap @@ -27,16 +26,4 @@ interface IHttpGetApi { @HeaderMap headers: Map ): Deferred> - @GET - fun get( - @Url url: String, - @HeaderMap headers: Map - ): Call - - @GET - fun getMap( - @Url url: String, - @QueryMap(encoded = true) queryMap: Map, - @HeaderMap headers: Map - ): Call } diff --git a/app/src/main/java/io/legado/app/data/api/IHttpPostApi.kt b/app/src/main/java/io/legado/app/data/api/IHttpPostApi.kt index 0aa3ef3db..21fb2622c 100644 --- a/app/src/main/java/io/legado/app/data/api/IHttpPostApi.kt +++ b/app/src/main/java/io/legado/app/data/api/IHttpPostApi.kt @@ -28,18 +28,4 @@ interface IHttpPostApi { @HeaderMap headers: Map ): Deferred> - @FormUrlEncoded - @POST - fun postMap( - @Url url: String, - @FieldMap(encoded = true) fieldMap: Map, - @HeaderMap headers: Map - ): Call - - @POST - fun postBody( - @Url url: String, - @Body body: RequestBody, - @HeaderMap headers: Map - ): Call } diff --git a/app/src/main/java/io/legado/app/help/coroutine/Coroutine.kt b/app/src/main/java/io/legado/app/help/coroutine/Coroutine.kt index 14dd69f14..5b8c3d2c0 100644 --- a/app/src/main/java/io/legado/app/help/coroutine/Coroutine.kt +++ b/app/src/main/java/io/legado/app/help/coroutine/Coroutine.kt @@ -1,6 +1,8 @@ package io.legado.app.help.coroutine +import android.util.Log import kotlinx.coroutines.* +import kotlin.coroutines.CoroutineContext class Coroutine(scope: CoroutineScope, block: suspend CoroutineScope.() -> T) { @@ -17,14 +19,12 @@ class Coroutine(scope: CoroutineScope, block: suspend CoroutineScope.() -> T) private val job: Job - private var start: (suspend CoroutineScope.() -> Unit)? = null - private var execute: (suspend CoroutineScope.(T?) -> Unit)? = null - private var success: (suspend CoroutineScope.(T?) -> Unit)? = null - private var error: (suspend CoroutineScope.(Throwable) -> Unit)? = null - private var finally: (suspend CoroutineScope.() -> Unit)? = null + private var start: VoidCallback? = null + private var success: Callback? = null + private var error: Callback? = null + private var finally: VoidCallback? = null private var timeMillis: Long? = null - private var errorReturn: Result? = null val isCancelled: Boolean @@ -37,9 +37,7 @@ class Coroutine(scope: CoroutineScope, block: suspend CoroutineScope.() -> T) get() = job.isCompleted init { - this.job = scope.plus(Dispatchers.Main).launch { - executeInternal(this@launch, block) - } + this.job = executeInternal(scope, block) } fun timeout(timeMillis: () -> Long): Coroutine { @@ -62,28 +60,35 @@ class Coroutine(scope: CoroutineScope, block: suspend CoroutineScope.() -> T) return this@Coroutine } - fun onStart(start: (suspend CoroutineScope.() -> Unit)): Coroutine { - this.start = start - return this@Coroutine - } - - fun onExecute(execute: suspend CoroutineScope.(T?) -> Unit): Coroutine { - this.execute = execute + fun onStart( + context: CoroutineContext? = null, + block: (suspend CoroutineScope.() -> Unit) + ): Coroutine { + this.start = VoidCallback(context, block) return this@Coroutine } - fun onSuccess(success: suspend CoroutineScope.(T?) -> Unit): Coroutine { - this.success = success + fun onSuccess( + context: CoroutineContext? = null, + block: suspend CoroutineScope.(T?) -> Unit + ): Coroutine { + this.success = Callback(context, block) return this@Coroutine } - fun onError(error: suspend CoroutineScope.(Throwable) -> Unit): Coroutine { - this.error = error + fun onError( + context: CoroutineContext? = null, + block: suspend CoroutineScope.(Throwable) -> Unit + ): Coroutine { + this.error = Callback(context, block) return this@Coroutine } - fun onFinally(finally: suspend CoroutineScope.() -> Unit): Coroutine { - this.finally = finally + fun onFinally( + context: CoroutineContext? = null, + block: suspend CoroutineScope.() -> Unit + ): Coroutine { + this.finally = VoidCallback(context, block) return this@Coroutine } @@ -96,50 +101,72 @@ class Coroutine(scope: CoroutineScope, block: suspend CoroutineScope.() -> T) return job.invokeOnCompletion(handler) } - private suspend fun executeInternal(scope: CoroutineScope, block: suspend CoroutineScope.() -> T) { - tryCatch( - { - start?.invoke(scope) - val result = executeBlockIO(block, timeMillis ?: 0L) - success?.invoke(scope, result) - }, - { e -> + private fun executeInternal(scope: CoroutineScope, block: suspend CoroutineScope.() -> T): Job { + return scope.plus(Dispatchers.Main).launch { + try { + start?.let { dispatchVoidCallback(this, it) } + val value = executeBlock(scope, timeMillis ?: 0L, block) + success?.let { dispatchCallback(this, value, it) } + } catch (e: Throwable) { val consume: Boolean = errorReturn?.value?.let { value -> - success?.invoke(scope, value) + success?.let { dispatchCallback(this, value, it) } true } ?: false if (!consume) { - error?.invoke(scope, e) + error?.let { dispatchCallback(this, e, it) } } - }, - { - finally?.invoke(scope) - }) + } finally { + finally?.let { dispatchVoidCallback(this, it) } + } + } } - private suspend fun executeBlockIO(block: suspend CoroutineScope.() -> T, timeMillis: Long): T? { - val execution = withContext(Dispatchers.IO) { - val result = block() - execute?.invoke(this, result) - result + private suspend inline fun dispatchVoidCallback(scope: CoroutineScope, callback: VoidCallback) { + if (null == callback.context) { + callback.block.invoke(scope) + } else { + withContext(scope.coroutineContext.plus(callback.context)) { + callback.block.invoke(this) + } } - return if (timeMillis > 0L) withTimeout(timeMillis) { execution } else execution } - private suspend fun tryCatch( - tryBlock: suspend () -> Unit, - errorBlock: (suspend (Throwable) -> Unit)? = null, - finallyBlock: (suspend () -> Unit)? = null + private suspend inline fun dispatchCallback( + scope: CoroutineScope, + value: R, + callback: Callback ) { - try { - tryBlock() - } catch (e: Throwable) { - errorBlock?.invoke(e) - } finally { - finallyBlock?.invoke() + if (null == callback.context) { + callback.block.invoke(scope, value) + } else { + withContext(scope.coroutineContext.plus(callback.context)) { + callback.block.invoke(this, value) + } + } + } + + private suspend inline fun executeBlock( + scope: CoroutineScope, + timeMillis: Long, + noinline block: suspend CoroutineScope.() -> T + ): T? { + return withContext(scope.coroutineContext.plus(Dispatchers.IO)) { + if (timeMillis > 0L) withTimeout(timeMillis) { + block() + } else block() } } private data class Result(val value: T?) + + private inner class VoidCallback( + val context: CoroutineContext?, + val block: suspend CoroutineScope.() -> Unit + ) + + private inner class Callback( + val context: CoroutineContext?, + val block: suspend CoroutineScope.(VALUE) -> Unit + ) } diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt index bb32ec0fa..c2950aae0 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt @@ -223,21 +223,4 @@ class AnalyzeUrl( .getMapAsync(url, fieldMap, headerMap) } } - - fun getResponse(): Call { - return when { - method == Method.POST -> HttpHelper.getApiService( - baseUrl - ).postBody( - url, - body, - headerMap - ) - fieldMap.isEmpty() -> HttpHelper.getApiService( - baseUrl - ).get(url, headerMap) - else -> HttpHelper.getApiService(baseUrl) - .getMap(url, fieldMap, headerMap) - } - } } diff --git a/app/src/main/java/io/legado/app/model/webbook/BookChapterList.kt b/app/src/main/java/io/legado/app/model/webbook/BookChapterList.kt index 2bf02391e..8d8b4c22d 100644 --- a/app/src/main/java/io/legado/app/model/webbook/BookChapterList.kt +++ b/app/src/main/java/io/legado/app/model/webbook/BookChapterList.kt @@ -52,7 +52,7 @@ object BookChapterList { var nextUrl = chapterData.nextUrl[0] while (nextUrl.isNotEmpty() && !nextUrlList.contains(nextUrl)) { nextUrlList.add(nextUrl) - AnalyzeUrl(ruleUrl = nextUrl, book = book).getResponse().execute() + AnalyzeUrl(ruleUrl = nextUrl, book = book).getResponseAsync().await() .body()?.let { nextBody -> chapterData = analyzeChapterList(nextBody, nextUrl, tocRule, listRule, book, bookSource) nextUrl = if (chapterData.nextUrl.isNotEmpty()) chapterData.nextUrl[0] else "" diff --git a/app/src/main/java/io/legado/app/model/webbook/BookContent.kt b/app/src/main/java/io/legado/app/model/webbook/BookContent.kt index a8e92444b..0b77b10a4 100644 --- a/app/src/main/java/io/legado/app/model/webbook/BookContent.kt +++ b/app/src/main/java/io/legado/app/model/webbook/BookContent.kt @@ -51,7 +51,7 @@ object BookContent { == NetworkUtils.getAbsoluteURL(baseUrl, nextChapterUrl) ) break nextUrlList.add(nextUrl) - AnalyzeUrl(ruleUrl = nextUrl, book = book).getResponse().execute() + AnalyzeUrl(ruleUrl = nextUrl, book = book).getResponseAsync().await() .body()?.let { nextBody -> contentData = analyzeContent(nextBody, contentRule, book, baseUrl) nextUrl = if (contentData.nextUrl.isNotEmpty()) contentData.nextUrl[0] else "" diff --git a/app/src/main/java/io/legado/app/ui/search/SearchViewModel.kt b/app/src/main/java/io/legado/app/ui/search/SearchViewModel.kt index f4faf69f7..1defc8695 100644 --- a/app/src/main/java/io/legado/app/ui/search/SearchViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/search/SearchViewModel.kt @@ -4,10 +4,14 @@ import android.app.Application import android.util.Log import io.legado.app.App import io.legado.app.base.BaseViewModel -import io.legado.app.data.entities.SearchBook import io.legado.app.help.coroutine.Coroutine import io.legado.app.model.WebBook -import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.cancel +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import java.lang.Exception +import java.util.concurrent.CancellationException class SearchViewModel(application: Application) : BaseViewModel(application) { private var task: Coroutine<*>? = null @@ -29,7 +33,7 @@ class SearchViewModel(application: Application) : BaseViewModel(application) { //task取消时自动取消 by (scope = this@execute) WebBook(item).searchBook(key, searchPage, scope = this@execute) .timeout(30000L) - .onExecute{ + .onSuccess(Dispatchers.IO) { it?.let { list -> App.db.searchBookDao().insert(*list.toTypedArray()) } @@ -43,14 +47,12 @@ class SearchViewModel(application: Application) : BaseViewModel(application) { task?.invokeOnCompletion { finally?.invoke() } + + } fun stop() { task?.cancel() } - override fun onCleared() { - super.onCleared() - task?.cancel() - } }