Don't recycle visible images

This commit is contained in:
FooIbar committed 2024-08-19 13:49:36 +08:00
1 parent a08b8e96e5
commit 5a46fc4573
3 files changed
+27 -13

No files matched your search

@@ -18,7 +18,6 @@
package com.hippo.ehviewer.image
import android.graphics.Bitmap
import android.graphics.drawable.Animatable
import androidx.compose.ui.unit.IntRect
import arrow.core.Either
import arrow.core.left
@@ -51,7 +50,7 @@ import java.nio.ByteBuffer
import okio.Path
import splitties.init.appCtx
class Image private constructor(image: CoilImage, private val src: AutoCloseable) {
class Image private constructor(image: CoilImage, private val src: ImageSource) {
val size = image.size
val rect = when (image) {
is BitmapImageWithRect -> image.rect
@@ -63,14 +62,12 @@ class Image private constructor(image: CoilImage, private val src: AutoCloseable
else -> image
}
var isRecyclable = true
@Synchronized
fun recycle() {
when (val image = innerImage ?: return) {
is DrawableImage -> {
(image.drawable as Animatable).stop()
image.drawable.callback = null
src.close()
}
is DrawableImage -> src.close()
is BitmapImage -> image.bitmap.recycle()
}
innerImage = null
@@ -11,6 +11,7 @@ import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
@@ -66,6 +67,17 @@ fun PagerItem(
val painter = remember(image) { image.toPainter() }
val grayScale by Settings.grayScale.collectAsState()
val invert by Settings.invertedColors.collectAsState()
DisposableEffect(image) {
image.isRecyclable = false
onDispose {
if (image.isRecyclable) {
pageLoader.notifyPageWait(page.index)
image.recycle()
} else {
image.isRecyclable = true
}
}
}
Image(
painter = painter,
contentDescription = null,
@@ -23,8 +23,12 @@ abstract class PageLoader {
},
sizeOf = { _, v -> v.size.toInt() },
onEntryRemoved = { _, k, o, n ->
n ?: notifyPageWait(k)
o.recycle()
if (o.isRecyclable) {
n ?: notifyPageWait(k)
o.recycle()
} else {
o.isRecyclable = true
}
},
)
}
@@ -63,7 +67,7 @@ abstract class PageLoader {
fun request(index: Int) {
val image = cache[index]
if (image != null) {
notifyPageSucceed(index, image)
notifyPageSucceed(index, image, false)
} else {
notifyPageWait(index)
onRequest(index)
@@ -107,16 +111,17 @@ abstract class PageLoader {
protected abstract fun onCancelRequest(index: Int)
fun notifyPageWait(index: Int) {
pages[index].progress = 0
pages[index].status.value = Page.State.QUEUE
}
fun notifyPagePercent(index: Int, percent: Float) {
pages[index].status.compareAndSet(Page.State.QUEUE, Page.State.DOWNLOAD_IMAGE)
pages[index].progress = (percent * 100).toInt()
pages[index].status.compareAndSet(Page.State.QUEUE, Page.State.DOWNLOAD_IMAGE)
}
fun notifyPageSucceed(index: Int, image: Image) {
if (cache[index] != image) {
fun notifyPageSucceed(index: Int, image: Image, replaceCache: Boolean = true) {
if (replaceCache) {
cache.put(index, image)
}
pages[index].image = image