Fix concurrent chapters loading in reader

This commit is contained in:
Koitharu
2023-05-17 16:17:18 +03:00
parent 2e0eb5de54
commit 51ff1ff7b7
5 changed files with 53 additions and 12 deletions

View File

@@ -8,19 +8,22 @@ abstract class BoundsScrollListener(private val offsetTop: Int, private val offs
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
if (recyclerView.hasPendingAdapterUpdates()) {
return
}
val layoutManager = (recyclerView.layoutManager as? LinearLayoutManager) ?: return
val firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition()
if (firstVisibleItemPosition == RecyclerView.NO_POSITION) {
return
}
if (firstVisibleItemPosition <= offsetTop) {
onScrolledToStart(recyclerView)
}
val visibleItemCount = layoutManager.childCount
val totalItemCount = layoutManager.itemCount
if (visibleItemCount + firstVisibleItemPosition >= totalItemCount - offsetBottom) {
onScrolledToEnd(recyclerView)
}
if (firstVisibleItemPosition <= offsetTop) {
onScrolledToStart(recyclerView)
}
}
abstract fun onScrolledToStart(recyclerView: RecyclerView)

View File

@@ -0,0 +1,30 @@
package org.koitharu.kotatsu.base.ui.list
import androidx.recyclerview.widget.RecyclerView
class ScrollListenerInvalidationObserver(
private val recyclerView: RecyclerView,
private val scrollListener: RecyclerView.OnScrollListener,
) : RecyclerView.AdapterDataObserver() {
override fun onChanged() {
super.onChanged()
invalidateScroll()
}
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
super.onItemRangeInserted(positionStart, itemCount)
invalidateScroll()
}
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
super.onItemRangeRemoved(positionStart, itemCount)
invalidateScroll()
}
private fun invalidateScroll() {
recyclerView.post {
scrollListener.onScrolled(recyclerView, 0, 0)
}
}
}

View File

@@ -252,6 +252,7 @@ class ReaderViewModel @Inject constructor(
val prevJob = stateChangeJob
stateChangeJob = launchJob(Dispatchers.Default) {
prevJob?.cancelAndJoin()
loadingJob?.join()
val pages = content.value?.pages ?: return@launchJob
pages.getOrNull(position)?.let { page ->
currentState.update { cs ->
@@ -263,12 +264,12 @@ class ReaderViewModel @Inject constructor(
return@launchJob
}
ensureActive()
if (position <= BOUNDS_PAGE_OFFSET) {
loadPrevNextChapter(pages.first().chapterId, isNext = false)
}
if (position >= pages.lastIndex - BOUNDS_PAGE_OFFSET) {
loadPrevNextChapter(pages.last().chapterId, isNext = true)
}
if (position <= BOUNDS_PAGE_OFFSET) {
loadPrevNextChapter(pages.first().chapterId, isNext = false)
}
if (pageLoader.isPrefetchApplicable()) {
pageLoader.prefetch(pages.trySublist(position + 1, position + PREFETCH_LIMIT))
}
@@ -348,7 +349,9 @@ class ReaderViewModel @Inject constructor(
@AnyThread
private fun loadPrevNextChapter(currentId: Long, isNext: Boolean) {
val prevJob = loadingJob
loadingJob = launchLoadingJob(Dispatchers.Default) {
prevJob?.join()
chaptersLoader.loadPrevNextChapter(mangaData.requireValue(), currentId, isNext)
content.emitValue(ReaderContent(chaptersLoader.snapshot(), null))
}

View File

@@ -54,6 +54,11 @@ var RecyclerView.firstVisibleItemPosition: Int
}
}
val RecyclerView.visibleItemCount: Int
get() = (layoutManager as? LinearLayoutManager)?.run {
findLastVisibleItemPosition() - findFirstVisibleItemPosition()
} ?: 0
fun View.hasGlobalPoint(x: Int, y: Int): Boolean {
if (visibility != View.VISIBLE) {
return false