mirror of
https://github.com/gedoor/legado.git
synced 2024-07-19 01:17:25 +08:00
优化
This commit is contained in:
parent
1111e36c41
commit
4551281e6f
@ -25,14 +25,19 @@ import io.legado.app.model.CacheBook
|
|||||||
import io.legado.app.model.ReadBook
|
import io.legado.app.model.ReadBook
|
||||||
import io.legado.app.model.webBook.WebBook
|
import io.legado.app.model.webBook.WebBook
|
||||||
import io.legado.app.service.CacheBookService
|
import io.legado.app.service.CacheBookService
|
||||||
|
import io.legado.app.utils.onEachParallel
|
||||||
import io.legado.app.utils.postEvent
|
import io.legado.app.utils.postEvent
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.asCoroutineDispatcher
|
import kotlinx.coroutines.asCoroutineDispatcher
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.flow.catch
|
||||||
|
import kotlinx.coroutines.flow.collect
|
||||||
|
import kotlinx.coroutines.flow.flow
|
||||||
|
import kotlinx.coroutines.flow.onCompletion
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.isActive
|
import kotlinx.coroutines.isActive
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.util.LinkedList
|
import java.util.LinkedList
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
@ -41,7 +46,7 @@ class MainViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
private var poolSize = min(threadCount, AppConst.MAX_THREAD)
|
private var poolSize = min(threadCount, AppConst.MAX_THREAD)
|
||||||
private var upTocPool = Executors.newFixedThreadPool(poolSize).asCoroutineDispatcher()
|
private var upTocPool = Executors.newFixedThreadPool(poolSize).asCoroutineDispatcher()
|
||||||
private val waitUpTocBooks = LinkedList<String>()
|
private val waitUpTocBooks = LinkedList<String>()
|
||||||
private val onUpTocBooks = ConcurrentHashMap.newKeySet<String>()
|
private val onUpTocBooks = hashSetOf<String>()
|
||||||
val onUpBooksLiveData = MutableLiveData<Int>()
|
val onUpBooksLiveData = MutableLiveData<Int>()
|
||||||
private var upTocJob: Job? = null
|
private var upTocJob: Job? = null
|
||||||
private var cacheBookJob: Job? = null
|
private var cacheBookJob: Job? = null
|
||||||
@ -101,86 +106,70 @@ class MainViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
upPool()
|
upPool()
|
||||||
postUpBooksLiveData()
|
postUpBooksLiveData()
|
||||||
upTocJob = viewModelScope.launch(upTocPool) {
|
upTocJob = viewModelScope.launch(upTocPool) {
|
||||||
while (isActive) {
|
flow {
|
||||||
when {
|
while (true) {
|
||||||
waitUpTocBooks.isEmpty() -> {
|
emit(waitUpTocBooks.poll() ?: break)
|
||||||
upTocJob?.cancel()
|
|
||||||
upTocJob = null
|
|
||||||
}
|
|
||||||
|
|
||||||
onUpTocBooks.size < threadCount -> {
|
|
||||||
updateToc()
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> {
|
|
||||||
delay(500)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}.onEach {
|
||||||
|
onUpTocBooks.add(it)
|
||||||
|
postEvent(EventBus.UP_BOOKSHELF, it)
|
||||||
|
}.onEachParallel(threadCount) {
|
||||||
|
updateToc(it)
|
||||||
|
}.onEach {
|
||||||
|
onUpTocBooks.remove(it)
|
||||||
|
postEvent(EventBus.UP_BOOKSHELF, it)
|
||||||
|
postUpBooksLiveData()
|
||||||
|
}.onCompletion {
|
||||||
|
upTocJob = null
|
||||||
|
if (it == null && cacheBookJob == null && !CacheBookService.isRun) {
|
||||||
|
//所有目录更新完再开始缓存章节
|
||||||
|
cacheBook()
|
||||||
|
}
|
||||||
|
}.catch {
|
||||||
|
AppLog.put("更新目录出错\n${it.localizedMessage}", it)
|
||||||
|
}.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
private suspend fun updateToc(bookUrl: String) {
|
||||||
private fun updateToc() {
|
val book = appDb.bookDao.getBook(bookUrl) ?: return
|
||||||
val bookUrl = waitUpTocBooks.poll() ?: return
|
|
||||||
if (onUpTocBooks.contains(bookUrl)) {
|
|
||||||
postUpBooksLiveData()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val book = appDb.bookDao.getBook(bookUrl)
|
|
||||||
if (book == null) {
|
|
||||||
postUpBooksLiveData()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val source = appDb.bookSourceDao.getBookSource(book.origin)
|
val source = appDb.bookSourceDao.getBookSource(book.origin)
|
||||||
if (source == null) {
|
if (source == null) {
|
||||||
if (!book.isUpError) {
|
if (!book.isUpError) {
|
||||||
book.addType(BookType.updateError)
|
book.addType(BookType.updateError)
|
||||||
appDb.bookDao.update(book)
|
appDb.bookDao.update(book)
|
||||||
}
|
}
|
||||||
postUpBooksLiveData()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
upTocAdd(bookUrl)
|
kotlin.runCatching {
|
||||||
execute(context = upTocPool, executeContext = upTocPool) {
|
val oldBook = book.copy()
|
||||||
kotlin.runCatching {
|
WebBook.runPreUpdateJs(source, book)
|
||||||
val oldBook = book.copy()
|
if (book.tocUrl.isBlank()) {
|
||||||
WebBook.runPreUpdateJs(source, book)
|
WebBook.getBookInfoAwait(source, book)
|
||||||
if (book.tocUrl.isBlank()) {
|
}
|
||||||
WebBook.getBookInfoAwait(source, book)
|
val toc = WebBook.getChapterListAwait(source, book).getOrThrow()
|
||||||
}
|
book.sync(oldBook)
|
||||||
val toc = WebBook.getChapterListAwait(source, book).getOrThrow()
|
book.removeType(BookType.updateError)
|
||||||
book.sync(oldBook)
|
if (book.bookUrl == bookUrl) {
|
||||||
book.removeType(BookType.updateError)
|
appDb.bookDao.update(book)
|
||||||
if (book.bookUrl == bookUrl) {
|
} else {
|
||||||
appDb.bookDao.update(book)
|
appDb.bookDao.insert(book)
|
||||||
} else {
|
BookHelp.updateCacheFolder(oldBook, book)
|
||||||
upTocAdd(book.bookUrl)
|
}
|
||||||
appDb.bookDao.insert(book)
|
appDb.bookChapterDao.delByBook(bookUrl)
|
||||||
BookHelp.updateCacheFolder(oldBook, book)
|
appDb.bookChapterDao.insert(*toc.toTypedArray())
|
||||||
}
|
if (book.isSameNameAuthor(ReadBook.book)) {
|
||||||
appDb.bookChapterDao.delByBook(bookUrl)
|
ReadBook.book = book
|
||||||
appDb.bookChapterDao.insert(*toc.toTypedArray())
|
ReadBook.chapterSize = book.totalChapterNum
|
||||||
if (book.isSameNameAuthor(ReadBook.book)) {
|
}
|
||||||
ReadBook.book = book
|
addDownload(source, book)
|
||||||
ReadBook.chapterSize = book.totalChapterNum
|
}.onFailure {
|
||||||
}
|
AppLog.put("${book.name} 更新目录失败\n${it.localizedMessage}", it)
|
||||||
addDownload(source, book)
|
//这里可能因为时间太长书籍信息已经更改,所以重新获取
|
||||||
}.onFailure {
|
appDb.bookDao.getBook(book.bookUrl)?.let { book ->
|
||||||
AppLog.put("${book.name} 更新目录失败\n${it.localizedMessage}", it)
|
book.addType(BookType.updateError)
|
||||||
//这里可能因为时间太长书籍信息已经更改,所以重新获取
|
appDb.bookDao.update(book)
|
||||||
appDb.bookDao.getBook(book.bookUrl)?.let { book ->
|
|
||||||
book.addType(BookType.updateError)
|
|
||||||
appDb.bookDao.update(book)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}.onCancel {
|
|
||||||
upTocCancel(bookUrl)
|
|
||||||
upTocCancel(book.bookUrl)
|
|
||||||
}.onFinally {
|
|
||||||
upTocFinally(bookUrl)
|
|
||||||
upTocFinally(book.bookUrl)
|
|
||||||
postUpBooksLiveData()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,33 +181,6 @@ class MainViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
|
||||||
private fun upTocAdd(bookUrl: String) {
|
|
||||||
onUpTocBooks.add(bookUrl)
|
|
||||||
postEvent(EventBus.UP_BOOKSHELF, bookUrl)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Synchronized
|
|
||||||
private fun upTocCancel(bookUrl: String) {
|
|
||||||
onUpTocBooks.remove(bookUrl)
|
|
||||||
waitUpTocBooks.add(bookUrl)
|
|
||||||
postEvent(EventBus.UP_BOOKSHELF, bookUrl)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Synchronized
|
|
||||||
private fun upTocFinally(bookUrl: String) {
|
|
||||||
onUpTocBooks.remove(bookUrl)
|
|
||||||
postEvent(EventBus.UP_BOOKSHELF, bookUrl)
|
|
||||||
if (waitUpTocBooks.isEmpty()
|
|
||||||
&& onUpTocBooks.isEmpty()
|
|
||||||
&& cacheBookJob == null
|
|
||||||
&& !CacheBookService.isRun
|
|
||||||
) {
|
|
||||||
//所有目录更新完再开始缓存章节
|
|
||||||
cacheBook()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
private fun addDownload(source: BookSource, book: Book) {
|
private fun addDownload(source: BookSource, book: Book) {
|
||||||
if (AppConfig.preDownloadNum == 0) return
|
if (AppConfig.preDownloadNum == 0) return
|
||||||
|
Loading…
Reference in New Issue
Block a user