某些设备的ANR问题
This commit is contained in:
@@ -63,6 +63,7 @@ class CacheBookModel(
|
||||
private var isLoading = false
|
||||
private var isPaused = false
|
||||
|
||||
@Synchronized
|
||||
private fun notifyDownloadSetChanged() {
|
||||
host.emitDownloadingIndices(book.bookUrl, onDownloadSet.toSet())
|
||||
if (host.cacheBookMap[book.bookUrl] === this) {
|
||||
@@ -75,6 +76,7 @@ class CacheBookModel(
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun notifyErrorChanged() {
|
||||
val errors = host.errorIndices(book.bookUrl)
|
||||
host.emitDownloadError(book.bookUrl, errors)
|
||||
@@ -260,41 +262,43 @@ class CacheBookModel(
|
||||
addDownload(index, index)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun onSuccess(chapter: BookChapter) {
|
||||
onDownloadSet.remove(chapter.index)
|
||||
chapterTasks.remove(chapter.index)
|
||||
host.incrementSuccessCount()
|
||||
retryCountMap.remove(chapter.index)
|
||||
host.stateStore.markSuccess(book.bookUrl, chapter.index)
|
||||
synchronized(this) {
|
||||
onDownloadSet.remove(chapter.index)
|
||||
chapterTasks.remove(chapter.index)
|
||||
host.incrementSuccessCount()
|
||||
retryCountMap.remove(chapter.index)
|
||||
host.stateStore.markSuccess(book.bookUrl, chapter.index)
|
||||
}
|
||||
notifyDownloadSetChanged()
|
||||
notifyErrorChanged()
|
||||
host.emitChapterCached(chapter)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun onPreError(chapter: BookChapter, error: Throwable) {
|
||||
waitingRetry = true
|
||||
if (error !is ConcurrentException) {
|
||||
retryCountMap[chapter.index] = (retryCountMap[chapter.index] ?: 0) + 1
|
||||
host.stateStore.markFailed(book.bookUrl, chapter.index)
|
||||
synchronized(this) {
|
||||
waitingRetry = true
|
||||
if (error !is ConcurrentException) {
|
||||
retryCountMap[chapter.index] = (retryCountMap[chapter.index] ?: 0) + 1
|
||||
host.stateStore.markFailed(book.bookUrl, chapter.index)
|
||||
}
|
||||
onDownloadSet.remove(chapter.index)
|
||||
chapterTasks.remove(chapter.index)
|
||||
}
|
||||
onDownloadSet.remove(chapter.index)
|
||||
chapterTasks.remove(chapter.index)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun onPostError(chapter: BookChapter, error: Throwable) {
|
||||
val retryCount = retryCountMap[chapter.index] ?: 0
|
||||
if (retryCount < 3 && !isStopped) {
|
||||
queue.enqueue(ChapterSelection.Single(chapter.index))
|
||||
} else {
|
||||
AppLog.put("下载${book.name}-${chapter.title}失败\n${error.localizedMessage}", error)
|
||||
synchronized(this) {
|
||||
val retryCount = retryCountMap[chapter.index] ?: 0
|
||||
if (retryCount < 3 && !isStopped) {
|
||||
queue.enqueue(ChapterSelection.Single(chapter.index))
|
||||
} else {
|
||||
AppLog.put("下载${book.name}-${chapter.title}失败\n${error.localizedMessage}", error)
|
||||
}
|
||||
waitingRetry = false
|
||||
}
|
||||
waitingRetry = false
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun onError(chapter: BookChapter, error: Throwable) {
|
||||
onPreError(chapter, error)
|
||||
onPostError(chapter, error)
|
||||
@@ -302,21 +306,25 @@ class CacheBookModel(
|
||||
notifyErrorChanged()
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun onCancel(index: Int, requeue: Boolean = true) {
|
||||
onDownloadSet.remove(index)
|
||||
chapterTasks.remove(index)
|
||||
val wasCanceled = canceledDownloadSet.remove(index)
|
||||
if (requeue && !isStopped && !wasCanceled) {
|
||||
queue.enqueue(ChapterSelection.Single(index))
|
||||
synchronized(this) {
|
||||
onDownloadSet.remove(index)
|
||||
chapterTasks.remove(index)
|
||||
val wasCanceled = canceledDownloadSet.remove(index)
|
||||
if (requeue && !isStopped && !wasCanceled) {
|
||||
queue.enqueue(ChapterSelection.Single(index))
|
||||
}
|
||||
}
|
||||
notifyDownloadSetChanged()
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun onFinally() {
|
||||
val shouldRemove: Boolean
|
||||
val bookUrl = book.bookUrl
|
||||
if (queue.waitingCount() == 0 && onDownloadSet.isEmpty() && pausedChapterSet.isEmpty()) {
|
||||
synchronized(this) {
|
||||
shouldRemove = queue.waitingCount() == 0 && onDownloadSet.isEmpty() && pausedChapterSet.isEmpty()
|
||||
}
|
||||
if (shouldRemove) {
|
||||
host.onTaskRemoved(bookUrl)
|
||||
} else {
|
||||
host.onTaskQueuesChanged(bookUrl)
|
||||
|
||||
@@ -207,8 +207,10 @@ object ImageProvider {
|
||||
}.getOrDefault(errorBitmap)
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
bitmapLruCache.evictAll()
|
||||
suspend fun clear() {
|
||||
withContext(IO) {
|
||||
bitmapLruCache.evictAll()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1108,10 +1108,13 @@ object ReadBook : CoroutineScope by MainScope(), KoinComponent {
|
||||
preDownloadTask?.cancel()
|
||||
downloadScope.coroutineContext.cancelChildren()
|
||||
coroutineContext.cancelChildren()
|
||||
ImageProvider.clear()
|
||||
clearExpiredChapterLoadingJob(true)
|
||||
if (!CacheBookService.isRun) {
|
||||
CacheBook.close()
|
||||
// Move expensive cleanup off the main thread
|
||||
CoroutineScope(SupervisorJob() + IO).launch {
|
||||
ImageProvider.clear()
|
||||
if (!CacheBookService.isRun) {
|
||||
CacheBook.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -212,9 +212,16 @@ class BookshelfViewModel(
|
||||
}
|
||||
combine(flows) { it.toMap() }
|
||||
}
|
||||
}.flowOn(Dispatchers.Default)
|
||||
}.distinctUntilChanged()
|
||||
.flowOn(Dispatchers.Default)
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyMap())
|
||||
|
||||
private val allGroupBooksImmutableFlow: StateFlow<ImmutableMap<Long, ImmutableList<BookShelfItem>>> =
|
||||
allGroupBooksFlow.map { map ->
|
||||
map.mapValues { it.value.toImmutableList() }.toImmutableMap()
|
||||
}.flowOn(Dispatchers.Default)
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), persistentMapOf())
|
||||
|
||||
private val visibleBooksFlow = combine(
|
||||
booksFlow,
|
||||
searchKeyFlow,
|
||||
@@ -366,7 +373,7 @@ class BookshelfViewModel(
|
||||
) { books, groups, allGroups, previews, internal ->
|
||||
BookshelfDataCore(books, groups, allGroups, previews, internal)
|
||||
},
|
||||
allGroupBooksFlow
|
||||
allGroupBooksImmutableFlow
|
||||
) { core, allGroupBooks ->
|
||||
BookshelfDataState(
|
||||
books = core.books,
|
||||
@@ -392,7 +399,7 @@ class BookshelfViewModel(
|
||||
val allGroups: List<BookGroupUi>,
|
||||
val previews: GroupPreviewState,
|
||||
val internal: InternalState,
|
||||
val allGroupBooks: Map<Long, List<BookShelfItem>>
|
||||
val allGroupBooks: ImmutableMap<Long, ImmutableList<BookShelfItem>>
|
||||
)
|
||||
|
||||
val uiState: StateFlow<BookshelfUiState> = combine(
|
||||
@@ -453,7 +460,7 @@ class BookshelfViewModel(
|
||||
currentGroupName = currentGroupName,
|
||||
draggingBooks = interaction.draggingBooks?.toImmutableList(),
|
||||
pendingSavedBooks = interaction.pendingSavedBooks?.toImmutableList(),
|
||||
allGroupBooks = data.allGroupBooks.mapValues { it.value.toImmutableList() }.toImmutableMap()
|
||||
allGroupBooks = data.allGroupBooks
|
||||
)
|
||||
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), BookshelfUiState())
|
||||
|
||||
|
||||
Reference in New Issue
Block a user