From 7b62b64178fa10a0f20a0a9441ef334e5bbebe96 Mon Sep 17 00:00:00 2001 From: kunfei Date: Tue, 18 Feb 2020 12:26:41 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io/legado/app/data/dao/BookChapterDao.kt | 3 + .../legado/app/data/entities/BookChapter.kt | 11 +++ .../io/legado/app/service/DownloadService.kt | 77 ++++++++++++++----- 3 files changed, 72 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/io/legado/app/data/dao/BookChapterDao.kt b/app/src/main/java/io/legado/app/data/dao/BookChapterDao.kt index 9dda87c0e..38cc452f2 100644 --- a/app/src/main/java/io/legado/app/data/dao/BookChapterDao.kt +++ b/app/src/main/java/io/legado/app/data/dao/BookChapterDao.kt @@ -19,6 +19,9 @@ interface BookChapterDao { @Query("select * from chapters where bookUrl = :bookUrl") fun getChapterList(bookUrl: String): List + @Query("select * from chapters where bookUrl = :bookUrl and `index` >= :start and `index` <= :end") + fun getChapterList(bookUrl: String, start: Int, end: Int): List + @Query("select * from chapters where bookUrl = :bookUrl and `index` = :index") fun getChapter(bookUrl: String, index: Int): BookChapter? diff --git a/app/src/main/java/io/legado/app/data/entities/BookChapter.kt b/app/src/main/java/io/legado/app/data/entities/BookChapter.kt index 77c1ce509..f7a008870 100644 --- a/app/src/main/java/io/legado/app/data/entities/BookChapter.kt +++ b/app/src/main/java/io/legado/app/data/entities/BookChapter.kt @@ -52,5 +52,16 @@ data class BookChapter( variable = GSON.toJson(variableMap) } + override fun hashCode(): Int { + return url.hashCode() + } + + override fun equals(other: Any?): Boolean { + if (other is BookChapter) { + return other.url == url + } + return false + } + } diff --git a/app/src/main/java/io/legado/app/service/DownloadService.kt b/app/src/main/java/io/legado/app/service/DownloadService.kt index df49e24d9..081b6d756 100644 --- a/app/src/main/java/io/legado/app/service/DownloadService.kt +++ b/app/src/main/java/io/legado/app/service/DownloadService.kt @@ -6,9 +6,10 @@ import androidx.core.app.NotificationCompat import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseService -import io.legado.app.constant.IntentAction import io.legado.app.constant.AppConst import io.legado.app.constant.EventBus +import io.legado.app.constant.IntentAction +import io.legado.app.data.entities.BookChapter import io.legado.app.help.AppConfig import io.legado.app.help.BookHelp import io.legado.app.help.IntentHelp @@ -17,6 +18,7 @@ import io.legado.app.model.WebBook import io.legado.app.utils.postEvent import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.asCoroutineDispatcher +import org.jetbrains.anko.toast import java.util.concurrent.Executors class DownloadService : BaseService() { @@ -25,6 +27,8 @@ class DownloadService : BaseService() { private var tasks: ArrayList> = arrayListOf() private val handler = Handler() private var runnable: Runnable = Runnable { upDownload() } + private val downloadMap = hashMapOf>() + private val finalMap = hashMapOf>() private var notificationContent = "正在启动下载" private val notificationBuilder by lazy { val builder = NotificationCompat.Builder(this, AppConst.channelIdDownload) @@ -48,7 +52,7 @@ class DownloadService : BaseService() { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { intent?.action?.let { action -> when (action) { - IntentAction.start -> download( + IntentAction.start -> addDownloadData( intent.getStringExtra("bookUrl"), intent.getIntExtra("start", 0), intent.getIntExtra("end", 0) @@ -67,28 +71,63 @@ class DownloadService : BaseService() { postEvent(EventBus.UP_DOWNLOAD, false) } - private fun download(bookUrl: String?, start: Int, end: Int) { - if (bookUrl == null) return - val task = Coroutine.async(this) { - val book = App.db.bookDao().getBook(bookUrl) ?: return@async - val bookSource = App.db.bookSourceDao().getBookSource(book.origin) ?: return@async - val webBook = WebBook(bookSource) - for (index in start..end) { - App.db.bookChapterDao().getChapter(bookUrl, index)?.let { chapter -> - if (!BookHelp.hasContent(book, chapter)) { - webBook.getContent(book, chapter, scope = this, context = searchPool) - .onStart { - notificationContent = chapter.title - } - .onSuccess(IO) { content -> - content?.let { - BookHelp.saveContent(book, chapter, content) + private fun addDownloadData(bookUrl: String?, start: Int, end: Int) { + bookUrl ?: return + if (downloadMap.containsKey(bookUrl)) { + toast("该书已在下载列表") + return + } + execute { + val chapterMap = downloadMap[bookUrl] ?: linkedSetOf().apply { + downloadMap[bookUrl] = this + } + App.db.bookChapterDao().getChapterList(bookUrl, start, end).let { + chapterMap.addAll(it) + } + download() + } + } + + private fun download() { + val task = Coroutine.async(this, context = searchPool) { + downloadMap.forEach { entry -> + if (!finalMap.containsKey(entry.key)) { + val book = App.db.bookDao().getBook(entry.key) ?: return@async + val bookSource = + App.db.bookSourceDao().getBookSource(book.origin) ?: return@async + val webBook = WebBook(bookSource) + entry.value.forEach { chapter -> + if (!BookHelp.hasContent(book, chapter)) { + webBook.getContent(book, chapter, scope = this, context = searchPool) + .onStart { + notificationContent = chapter.title + } + .onSuccess(IO) { content -> + content?.let { + BookHelp.saveContent(book, chapter, content) + } } - } + .onFinally(IO) { + synchronized(this@DownloadService) { + val chapterMap = + finalMap[book.bookUrl] + ?: linkedSetOf().apply { + finalMap[book.bookUrl] = this + } + chapterMap.add(chapter) + if (chapterMap.size == entry.value.size) { + downloadMap.remove(book.bookUrl) + finalMap.remove(book.bookUrl) + } + } + } + } } } + } } + tasks.add(task) task.invokeOnCompletion { tasks.remove(task)