PageLoader improvements

This commit is contained in:
Koitharu
2024-01-05 10:46:32 +02:00
parent 7247cba855
commit 58e570601d
2 changed files with 19 additions and 27 deletions

View File

@@ -9,7 +9,6 @@ import androidx.collection.LongSparseArray
import androidx.collection.set import androidx.collection.set
import androidx.core.net.toUri import androidx.core.net.toUri
import dagger.hilt.android.ActivityRetainedLifecycle import dagger.hilt.android.ActivityRetainedLifecycle
import dagger.hilt.android.lifecycle.RetainedLifecycle
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.android.scopes.ActivityRetainedScoped import dagger.hilt.android.scopes.ActivityRetainedScoped
import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineExceptionHandler
@@ -53,6 +52,7 @@ import java.io.File
import java.util.LinkedList import java.util.LinkedList
import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicInteger
import javax.inject.Inject import javax.inject.Inject
import kotlin.concurrent.Volatile
import kotlin.coroutines.AbstractCoroutineContextElement import kotlin.coroutines.AbstractCoroutineContextElement
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
@@ -65,11 +65,7 @@ class PageLoader @Inject constructor(
private val settings: AppSettings, private val settings: AppSettings,
private val mangaRepositoryFactory: MangaRepository.Factory, private val mangaRepositoryFactory: MangaRepository.Factory,
private val imageProxyInterceptor: ImageProxyInterceptor, private val imageProxyInterceptor: ImageProxyInterceptor,
) : RetainedLifecycle.OnClearedListener { ) {
init {
lifecycle.addOnClearedListener(this)
}
val loaderScope = RetainedLifecycleCoroutineScope(lifecycle) + InternalErrorHandler() + Dispatchers.Default val loaderScope = RetainedLifecycleCoroutineScope(lifecycle) + InternalErrorHandler() + Dispatchers.Default
@@ -77,17 +73,12 @@ class PageLoader @Inject constructor(
private val semaphore = Semaphore(3) private val semaphore = Semaphore(3)
private val convertLock = Mutex() private val convertLock = Mutex()
private val prefetchLock = Mutex() private val prefetchLock = Mutex()
@Volatile
private var repository: MangaRepository? = null private var repository: MangaRepository? = null
private val prefetchQueue = LinkedList<MangaPage>() private val prefetchQueue = LinkedList<MangaPage>()
private val counter = AtomicInteger(0) private val counter = AtomicInteger(0)
private var prefetchQueueLimit = PREFETCH_LIMIT_DEFAULT // TODO adaptive private var prefetchQueueLimit = PREFETCH_LIMIT_DEFAULT // TODO adaptive
override fun onCleared() {
synchronized(tasks) {
tasks.clear()
}
}
fun isPrefetchApplicable(): Boolean { fun isPrefetchApplicable(): Boolean {
return repository is RemoteMangaRepository return repository is RemoteMangaRepository
&& settings.isPagesPreloadEnabled && settings.isPagesPreloadEnabled
@@ -131,20 +122,18 @@ class PageLoader @Inject constructor(
return loadPageAsync(page, force).await() return loadPageAsync(page, force).await()
} }
suspend fun convertInPlace(file: File) { suspend fun tryConvert(file: File): Boolean = convertLock.withLock {
convertLock.withLock { if (context.ramAvailable < file.length() * 2) {
if (context.ramAvailable < file.length() * 2) { return@withLock false
return@withLock }
} runInterruptible(Dispatchers.Default) {
runInterruptible(Dispatchers.Default) { val image = BitmapFactory.decodeFile(file.absolutePath)
val image = BitmapFactory.decodeFile(file.absolutePath) try {
try { file.outputStream().use { out ->
file.outputStream().use { out -> image.compress(Bitmap.CompressFormat.PNG, 100, out)
image.compress(Bitmap.CompressFormat.PNG, 100, out)
}
} finally {
image.recycle()
} }
} finally {
image.recycle()
} }
} }
} }
@@ -237,7 +226,7 @@ class PageLoader @Inject constructor(
companion object { companion object {
private const val PROGRESS_UNDEFINED = -1f private const val PROGRESS_UNDEFINED = -1f
private const val PREFETCH_LIMIT_DEFAULT = 10 private const val PREFETCH_LIMIT_DEFAULT = 6
private const val PREFETCH_MIN_RAM_MB = 80L private const val PREFETCH_MIN_RAM_MB = 80L
fun createPageRequest(page: MangaPage, pageUrl: String) = Request.Builder() fun createPageRequest(page: MangaPage, pageUrl: String) = Request.Builder()

View File

@@ -140,7 +140,10 @@ class PageHolderDelegate(
state = State.CONVERTING state = State.CONVERTING
try { try {
val file = uri.toFile() val file = uri.toFile()
loader.convertInPlace(file) if (!loader.tryConvert(file)) {
state = State.ERROR
callback.onError(e)
}
state = State.CONVERTED state = State.CONVERTED
callback.onImageReady(file.toUri()) callback.onImageReady(file.toUri())
} catch (ce: CancellationException) { } catch (ce: CancellationException) {