From 7ef313dc4d90d73c9f66126b9d8e120327750f4a Mon Sep 17 00:00:00 2001 From: 821938089 <821938089@qq.com> Date: Tue, 26 Jul 2022 21:57:26 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io/legado/app/help/coroutine/Coroutine.kt | 1 + .../java/io/legado/app/model/CacheBook.kt | 30 ++++++++++++++++--- .../io/legado/app/service/CacheBookService.kt | 7 +++++ .../legado/app/ui/book/cache/CacheActivity.kt | 1 + .../legado/app/ui/book/cache/CacheAdapter.kt | 4 +-- .../io/legado/app/ui/main/MainViewModel.kt | 13 ++++---- 6 files changed, 44 insertions(+), 12 deletions(-) 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 5e98d7e18..01612b877 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 @@ -147,6 +147,7 @@ class Coroutine( } catch (e: Throwable) { e.printOnDebug() if (e is CancellationException && e !is TimeoutCancellationException) { + this@Coroutine.cancel() return@launch } val consume: Boolean = errorReturn?.value?.let { value -> diff --git a/app/src/main/java/io/legado/app/model/CacheBook.kt b/app/src/main/java/io/legado/app/model/CacheBook.kt index d132a6f18..291cb666a 100644 --- a/app/src/main/java/io/legado/app/model/CacheBook.kt +++ b/app/src/main/java/io/legado/app/model/CacheBook.kt @@ -135,6 +135,8 @@ object CacheBook { private val onDownloadSet = linkedSetOf() private val successDownloadSet = linkedSetOf() private val errorDownloadMap = hashMapOf() + private var isStopped = false + private var waitingRetry = false val waitCount get() = waitDownloadSet.size val onDownloadCount get() = onDownloadSet.size @@ -146,13 +148,20 @@ object CacheBook { return waitDownloadSet.size > 0 || onDownloadSet.size > 0 } + @Synchronized + fun isStop(): Boolean { + return isStopped || (!isRun() && !waitingRetry) + } + @Synchronized fun stop() { waitDownloadSet.clear() + isStopped = true } @Synchronized fun addDownload(start: Int, end: Int) { + isStopped = false for (i in start..end) { if (!onDownloadSet.contains(i)) { waitDownloadSet.add(i) @@ -168,13 +177,18 @@ object CacheBook { } @Synchronized - private fun onError(index: Int, error: Throwable, chapterTitle: String) { + private fun onPreError(index: Int, error: Throwable) { + waitingRetry = true if (error !is ConcurrentException) { errorDownloadMap[index] = (errorDownloadMap[index] ?: 0) + 1 } onDownloadSet.remove(index) + } + + @Synchronized + private fun onPostError(index: Int, error: Throwable, chapterTitle: String) { //重试3次 - if ((errorDownloadMap[index] ?: 0) < 3) { + if ((errorDownloadMap[index] ?: 0) < 3 && !isStopped) { waitDownloadSet.add(index) } else { AppLog.put( @@ -182,12 +196,19 @@ object CacheBook { error ) } + waitingRetry = false + } + + @Synchronized + private fun onError(index: Int, error: Throwable, chapterTitle: String) { + onPreError(index, error) + onPostError(index, error, chapterTitle) } @Synchronized private fun onCancel(index: Int) { onDownloadSet.remove(index) - waitDownloadSet.add(index) + if (!isStopped) waitDownloadSet.add(index) } @Synchronized @@ -234,9 +255,10 @@ object CacheBook { onSuccess(chapterIndex) downloadFinish(chapter, content) }.onError { + onPreError(chapterIndex, it) //出现错误等待一秒后重新加入待下载列表 delay(1000) - onError(chapterIndex, it, chapter.title) + onPostError(chapterIndex, it, chapter.title) downloadFinish(chapter, "获取正文失败\n${it.localizedMessage}") }.onCancel { onCancel(chapterIndex) diff --git a/app/src/main/java/io/legado/app/service/CacheBookService.kt b/app/src/main/java/io/legado/app/service/CacheBookService.kt index 3407c7034..d15d07c1d 100644 --- a/app/src/main/java/io/legado/app/service/CacheBookService.kt +++ b/app/src/main/java/io/legado/app/service/CacheBookService.kt @@ -74,6 +74,7 @@ class CacheBookService : BaseService() { override fun onDestroy() { isRun = false cachePool.close() + CacheBook.cacheBookMap.forEach { it.value.stop() } CacheBook.cacheBookMap.clear() super.onDestroy() postEvent(EventBus.UP_DOWNLOAD, "") @@ -84,6 +85,7 @@ class CacheBookService : BaseService() { execute { val cacheBook = CacheBook.getOrCreate(bookUrl) ?: return@execute cacheBook.addDownload(start, end) + postEvent(EventBus.UP_DOWNLOAD, "") upNotification(CacheBook.downloadSummary) if (downloadJob == null) { download() @@ -93,6 +95,11 @@ class CacheBookService : BaseService() { private fun removeDownload(bookUrl: String?) { CacheBook.cacheBookMap[bookUrl]?.stop() + postEvent(EventBus.UP_DOWNLOAD, "") + if (downloadJob == null && CacheBook.isRun) { + download() + return + } if (CacheBook.cacheBookMap.isEmpty()) { stopSelf() } diff --git a/app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt b/app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt index 7264ee87f..26d3e2b90 100644 --- a/app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt @@ -237,6 +237,7 @@ class CacheActivity : VMBaseActivity() observeEvent(EventBus.SAVE_CONTENT) { adapter.cacheChapters[it.bookUrl]?.add(it.url) } + postEventDelay(EventBus.UP_DOWNLOAD, "", 100) } override fun export(position: Int) { diff --git a/app/src/main/java/io/legado/app/ui/book/cache/CacheAdapter.kt b/app/src/main/java/io/legado/app/ui/book/cache/CacheAdapter.kt index 4a4e601c4..10d31a4cb 100644 --- a/app/src/main/java/io/legado/app/ui/book/cache/CacheAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/cache/CacheAdapter.kt @@ -67,7 +67,7 @@ class CacheAdapter(context: Context, private val callBack: CallBack) : ivDownload.setOnClickListener { getItem(holder.layoutPosition)?.let { book -> CacheBook.cacheBookMap[book.bookUrl]?.let { - if (it.isRun()) { + if (!it.isStop()) { CacheBook.remove(context, book.bookUrl) } else { CacheBook.start(context, book, 0, book.totalChapterNum) @@ -89,7 +89,7 @@ class CacheAdapter(context: Context, private val callBack: CallBack) : } else { iv.visible() CacheBook.cacheBookMap[book.bookUrl]?.let { - if (it.isRun()) { + if (!it.isStop()) { iv.setImageResource(R.drawable.ic_stop_black_24dp) } else { iv.setImageResource(R.drawable.ic_play_24dp) diff --git a/app/src/main/java/io/legado/app/ui/main/MainViewModel.kt b/app/src/main/java/io/legado/app/ui/main/MainViewModel.kt index 69dea8cfe..ef0dcab63 100644 --- a/app/src/main/java/io/legado/app/ui/main/MainViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/main/MainViewModel.kt @@ -186,13 +186,14 @@ class MainViewModel(application: Application) : BaseViewModel(application) { private fun cacheBook() { cacheBookJob?.cancel() cacheBookJob = viewModelScope.launch(upTocPool) { - while (isActive) { - if (CacheBookService.isRun) { - cacheBookJob?.cancel() - cacheBookJob = null - return@launch + launch { + while (isActive) { + postEvent(EventBus.UP_DOWNLOAD, "") + delay(1000) } - if (!CacheBook.isRun) { + } + while (isActive) { + if (CacheBookService.isRun || !CacheBook.isRun) { cacheBookJob?.cancel() cacheBookJob = null return@launch From 01af2c35b5a168d26790fa2f257c6e541a09452b Mon Sep 17 00:00:00 2001 From: 821938089 <821938089@qq.com> Date: Wed, 27 Jul 2022 07:57:25 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/io/legado/app/help/coroutine/Coroutine.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 01612b877..36a21428c 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 @@ -40,6 +40,8 @@ class Coroutine( private var timeMillis: Long? = null private var errorReturn: Result? = null + private var isCancelCalled = false + val isCancelled: Boolean get() = job.isCancelled @@ -115,6 +117,7 @@ class Coroutine( //取消当前任务 fun cancel(cause: CancellationException? = null) { + isCancelCalled = true job.cancel(cause) cancel?.let { MainScope().launch { @@ -146,8 +149,8 @@ class Coroutine( success?.let { dispatchCallback(this, value, it) } } catch (e: Throwable) { e.printOnDebug() + if (e is CancellationException && !isCancelCalled) this@Coroutine.cancel() if (e is CancellationException && e !is TimeoutCancellationException) { - this@Coroutine.cancel() return@launch } val consume: Boolean = errorReturn?.value?.let { value ->