[修复] Bitmap 未正确回收导致的闪退问题
This commit is contained in:
@@ -70,12 +70,9 @@ object ImageProvider {
|
||||
removeCount++
|
||||
}
|
||||
}
|
||||
//错误图片不能释放,占位用,防止一直重复获取图片
|
||||
if (oldValue != errorBitmap) {
|
||||
oldValue.recycle()
|
||||
//putDebug("ImageProvider: trigger bitmap recycle. URI: $filePath")
|
||||
//putDebug("ImageProvider : cacheUsage ${size()}bytes / ${maxSize()}bytes")
|
||||
}
|
||||
// 移除 oldValue.recycle()。
|
||||
// 在 Android 8.0+ 像素内存由 GC 自动管理,手动回收容易导致 Canvas 绘制时崩溃。
|
||||
// 特别是在阅读页返回书架时,DisplayList 可能仍持有 Bitmap 引用。
|
||||
}
|
||||
|
||||
}
|
||||
@@ -86,7 +83,12 @@ object ImageProvider {
|
||||
}
|
||||
|
||||
fun get(key: String): Bitmap? {
|
||||
return bitmapLruCache[key]
|
||||
val bitmap = bitmapLruCache[key] ?: return null
|
||||
if (bitmap.isRecycled) {
|
||||
bitmapLruCache.remove(key)
|
||||
return null
|
||||
}
|
||||
return bitmap
|
||||
}
|
||||
|
||||
fun remove(key: String): Bitmap? {
|
||||
|
||||
@@ -4,7 +4,6 @@ import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.RectF
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.os.Build
|
||||
import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
@@ -617,13 +616,10 @@ class ReadView(context: Context, attrs: AttributeSet) :
|
||||
* 更新背景
|
||||
*/
|
||||
fun upBg() {
|
||||
val oldBg = ReadBookConfig.upBg(width, height)
|
||||
ReadBookConfig.upBg(width, height)
|
||||
curPage.upBg()
|
||||
prevPage.upBg()
|
||||
nextPage.upBg()
|
||||
// 所有视图背景更新完成后再 recycle 旧 bitmap,
|
||||
// 防止视图仍持有旧 BitmapDrawable 引用时 bitmap 已被 recycle 导致崩溃
|
||||
(oldBg as? BitmapDrawable)?.bitmap?.recycle()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,6 +25,7 @@ class FadePageDelegate(readView: ReadView) : PageDelegate(readView) {
|
||||
}
|
||||
|
||||
private fun setBitmap() {
|
||||
if (!readView.isAttachedToWindow) return
|
||||
when (mDirection) {
|
||||
PageDirection.PREV -> {
|
||||
prevPage.screenshot(prevRecorder)
|
||||
@@ -60,7 +61,6 @@ class FadePageDelegate(readView: ReadView) : PageDelegate(readView) {
|
||||
if (!isMoved || mDirection == PageDirection.NONE) return
|
||||
// 超过阈值自动翻页,否则回弹
|
||||
val shouldFlip = fadeProgress >= flipThreshold
|
||||
if (shouldFlip) 1f else 0f
|
||||
isCancel = !shouldFlip
|
||||
onAnimStart(readView.defaultAnimationSpeed)
|
||||
}
|
||||
@@ -97,13 +97,15 @@ class FadePageDelegate(readView: ReadView) : PageDelegate(readView) {
|
||||
}
|
||||
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
curRecorder.draw(canvas)
|
||||
if (!readView.isAttachedToWindow) return
|
||||
|
||||
if (mDirection == PageDirection.NONE) {
|
||||
// 直接绘制 curPage,不使用 curRecorder
|
||||
curPage.draw(canvas)
|
||||
return
|
||||
}
|
||||
|
||||
curRecorder.draw(canvas)
|
||||
|
||||
val alpha = (fadeProgress * 255).toInt().coerceIn(0, 255)
|
||||
val paint = Paint().apply { this.alpha = alpha }
|
||||
|
||||
@@ -143,11 +145,12 @@ class FadePageDelegate(readView: ReadView) : PageDelegate(readView) {
|
||||
readView.fillPage(mDirection)
|
||||
// 延迟更新 curRecorder,确保 curPage 已经刷新
|
||||
readView.post {
|
||||
try {
|
||||
curPage.screenshot(curRecorder)
|
||||
readView.invalidate()
|
||||
} catch (_: Exception) {
|
||||
// 捕获可能的异常,避免闪退
|
||||
if (readView.isAttachedToWindow) {
|
||||
try {
|
||||
curPage.screenshot(curRecorder)
|
||||
readView.invalidate()
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -168,12 +171,17 @@ class FadePageDelegate(readView: ReadView) : PageDelegate(readView) {
|
||||
isMoved = false
|
||||
isRunning = false
|
||||
if (!scroller.isFinished) {
|
||||
readView.isAbortAnim = true
|
||||
scroller.abortAnimation()
|
||||
if (!isCancel) {
|
||||
readView.fillPage(mDirection)
|
||||
curPage.screenshot(curRecorder) // 同步 curRecorder
|
||||
if (readView.isAttachedToWindow) {
|
||||
curPage.screenshot(curRecorder)
|
||||
}
|
||||
readView.invalidate()
|
||||
}
|
||||
} else {
|
||||
readView.isAbortAnim = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,15 +51,17 @@ class CanvasRecorderImpl : BaseCanvasRecorder() {
|
||||
}
|
||||
|
||||
override fun draw(canvas: Canvas) {
|
||||
if (bitmap == null) return
|
||||
canvas.drawBitmap(bitmap!!, 0f, 0f, null)
|
||||
val b = bitmap ?: return
|
||||
if (!b.isRecycled) {
|
||||
canvas.drawBitmap(b, 0f, 0f, null)
|
||||
}
|
||||
}
|
||||
|
||||
override fun recycle() {
|
||||
super.recycle()
|
||||
val bitmap = bitmap ?: return
|
||||
bitmapPool.put(bitmap)
|
||||
this.bitmap = null
|
||||
val b = bitmap ?: return
|
||||
bitmap = null
|
||||
bitmapPool.put(b)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
Reference in New Issue
Block a user