diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/ReadView.kt b/app/src/main/java/io/legado/app/ui/book/read/page/ReadView.kt index 58e2f1ffa..fff5a04f9 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/ReadView.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/ReadView.kt @@ -31,6 +31,7 @@ import io.legado.app.ui.book.read.page.provider.ChapterProvider import io.legado.app.ui.book.read.page.provider.LayoutProgressListener import io.legado.app.ui.book.read.page.provider.TextPageFactory import io.legado.app.utils.activity +import io.legado.app.utils.canvasrecorder.pools.BitmapPool import io.legado.app.utils.invisible import io.legado.app.utils.showDialogFragment import io.legado.app.utils.throttle @@ -461,6 +462,7 @@ class ReadView(context: Context, attrs: AttributeSet) : pageDelegate?.onDestroy() curPage.cancelSelect() invalidateTextPage() + BitmapPool.clear() } /** diff --git a/app/src/main/java/io/legado/app/utils/canvasrecorder/CanvasRecorderImpl.kt b/app/src/main/java/io/legado/app/utils/canvasrecorder/CanvasRecorderImpl.kt index 3cd205292..59e3c5cb0 100644 --- a/app/src/main/java/io/legado/app/utils/canvasrecorder/CanvasRecorderImpl.kt +++ b/app/src/main/java/io/legado/app/utils/canvasrecorder/CanvasRecorderImpl.kt @@ -16,14 +16,14 @@ class CanvasRecorderImpl : BaseCanvasRecorder() { private fun init(width: Int, height: Int) { if (bitmap == null) { - bitmap = bitmapPool.obtain(width, height) + bitmap = BitmapPool.obtain(width, height) } if (bitmap!!.width != width || bitmap!!.height != height) { if (canReconfigure(width, height)) { bitmap!!.reconfigure(width, height, Bitmap.Config.ARGB_8888) } else { - bitmapPool.recycle(bitmap!!) - bitmap = bitmapPool.obtain(width, height) + BitmapPool.recycle(bitmap!!) + bitmap = BitmapPool.obtain(width, height) } } } @@ -54,13 +54,12 @@ class CanvasRecorderImpl : BaseCanvasRecorder() { override fun recycle() { super.recycle() val bitmap = bitmap ?: return - bitmapPool.recycle(bitmap) + BitmapPool.recycle(bitmap) this.bitmap = null } companion object { private val canvasPool = CanvasPool(2) - private val bitmapPool = BitmapPool() } } diff --git a/app/src/main/java/io/legado/app/utils/canvasrecorder/pools/BitmapPool.kt b/app/src/main/java/io/legado/app/utils/canvasrecorder/pools/BitmapPool.kt index 62c5845e3..a9539035e 100644 --- a/app/src/main/java/io/legado/app/utils/canvasrecorder/pools/BitmapPool.kt +++ b/app/src/main/java/io/legado/app/utils/canvasrecorder/pools/BitmapPool.kt @@ -1,15 +1,46 @@ package io.legado.app.utils.canvasrecorder.pools import android.graphics.Bitmap -import java.lang.ref.SoftReference +import io.legado.app.help.globalExecutor import java.util.concurrent.ConcurrentHashMap -class BitmapPool { +object BitmapPool { - private val reusableBitmaps: MutableSet> = ConcurrentHashMap.newKeySet() + private val reusableBitmaps: MutableSet = ConcurrentHashMap.newKeySet() fun recycle(bitmap: Bitmap) { - reusableBitmaps.add(SoftReference(bitmap)) + reusableBitmaps.add(bitmap) + trimSize() + } + + fun clear() { + if (reusableBitmaps.isEmpty()) { + return + } + globalExecutor.execute { + val iterator = reusableBitmaps.iterator() + while (iterator.hasNext()) { + val item = iterator.next() + iterator.remove() + item.recycle() + } + } + } + + private fun trimSize() { + globalExecutor.execute { + var byteCount = 0 + val iterator = reusableBitmaps.iterator() + while (iterator.hasNext()) { + val item = iterator.next() + if (byteCount > 64 * 1024 * 1024) { + iterator.remove() + item.recycle() + } else { + byteCount += item.byteCount + } + } + } } fun obtain(width: Int, height: Int): Bitmap { @@ -18,7 +49,7 @@ class BitmapPool { } val iterator = reusableBitmaps.iterator() while (iterator.hasNext()) { - val item = iterator.next().get() ?: continue + val item = iterator.next() if (item.isMutable) { // Check to see it the item can be used for inBitmap. if (canReconfigure(item, width, height)) {