|
|
@ -3,6 +3,7 @@ package io.legado.app.ui.book.read.page.provider |
|
|
|
import android.graphics.Bitmap |
|
|
|
import android.graphics.Bitmap |
|
|
|
import android.graphics.BitmapFactory |
|
|
|
import android.graphics.BitmapFactory |
|
|
|
import android.util.Size |
|
|
|
import android.util.Size |
|
|
|
|
|
|
|
import androidx.collection.LruCache |
|
|
|
import io.legado.app.R |
|
|
|
import io.legado.app.R |
|
|
|
import io.legado.app.constant.AppLog.putDebug |
|
|
|
import io.legado.app.constant.AppLog.putDebug |
|
|
|
import io.legado.app.data.entities.Book |
|
|
|
import io.legado.app.data.entities.Book |
|
|
@ -23,6 +24,33 @@ object ImageProvider { |
|
|
|
BitmapFactory.decodeResource(appCtx.resources, R.drawable.image_loading_error) |
|
|
|
BitmapFactory.decodeResource(appCtx.resources, R.drawable.image_loading_error) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
*缓存bitmap LruCache实现 |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
//private val maxMemory = Runtime.getRuntime().maxMemory() |
|
|
|
|
|
|
|
//private val cacheMemorySize = (maxMemory / 8) as Int |
|
|
|
|
|
|
|
private val cacheMemorySize: Int = 1024 * 1024 * 1024 //1G |
|
|
|
|
|
|
|
private val bitmapLruCache = object : LruCache<String, Bitmap>(cacheMemorySize) { |
|
|
|
|
|
|
|
override fun sizeOf(key: String, bitmap: Bitmap): Int { |
|
|
|
|
|
|
|
return bitmap.getByteCount() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
override fun entryRemoved( |
|
|
|
|
|
|
|
evicted: Boolean, |
|
|
|
|
|
|
|
key: String, |
|
|
|
|
|
|
|
oldBitmap: Bitmap, |
|
|
|
|
|
|
|
newBitmap: Bitmap? |
|
|
|
|
|
|
|
) { |
|
|
|
|
|
|
|
if (evicted) { |
|
|
|
|
|
|
|
oldBitmap.recycle() |
|
|
|
|
|
|
|
putDebug("自动回收Bitmap path: $key") |
|
|
|
|
|
|
|
putDebug("bitmapLruCache : ${size()} / ${maxSize()}") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
*缓存网络图片和epub图片 |
|
|
|
|
|
|
|
*/ |
|
|
|
suspend fun cacheImage( |
|
|
|
suspend fun cacheImage( |
|
|
|
book: Book, |
|
|
|
book: Book, |
|
|
|
src: String, |
|
|
|
src: String, |
|
|
@ -45,6 +73,9 @@ object ImageProvider { |
|
|
|
return vFile |
|
|
|
return vFile |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
*获取图片宽度高度信息 |
|
|
|
|
|
|
|
*/ |
|
|
|
suspend fun getImageSize( |
|
|
|
suspend fun getImageSize( |
|
|
|
book: Book, |
|
|
|
book: Book, |
|
|
|
src: String, |
|
|
|
src: String, |
|
|
@ -58,16 +89,23 @@ object ImageProvider { |
|
|
|
return Size(op.outWidth, op.outHeight) |
|
|
|
return Size(op.outWidth, op.outHeight) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
*获取bitmap 使用LruCache缓存 |
|
|
|
|
|
|
|
*/ |
|
|
|
fun getImage( |
|
|
|
fun getImage( |
|
|
|
book: Book, |
|
|
|
book: Book, |
|
|
|
src: String, |
|
|
|
src: String, |
|
|
|
width: Int, |
|
|
|
width: Int, |
|
|
|
height: Int |
|
|
|
height: Int |
|
|
|
): Bitmap { |
|
|
|
): Bitmap { |
|
|
|
|
|
|
|
val cacheBitmap = bitmapLruCache.get(src) |
|
|
|
|
|
|
|
if (cacheBitmap != null) return cacheBitmap |
|
|
|
val vFile = BookHelp.getImage(book, src) |
|
|
|
val vFile = BookHelp.getImage(book, src) |
|
|
|
@Suppress("BlockingMethodInNonBlockingContext") |
|
|
|
@Suppress("BlockingMethodInNonBlockingContext") |
|
|
|
return try { |
|
|
|
return try { |
|
|
|
BitmapUtils.decodeBitmap(vFile.absolutePath, width, height) |
|
|
|
val bitmap = BitmapUtils.decodeBitmap(vFile.absolutePath, width, height) |
|
|
|
|
|
|
|
bitmapLruCache.put(src, bitmap) |
|
|
|
|
|
|
|
bitmap |
|
|
|
} catch (e: Exception) { |
|
|
|
} catch (e: Exception) { |
|
|
|
Coroutine.async { |
|
|
|
Coroutine.async { |
|
|
|
putDebug("${vFile.absolutePath} 解码失败\n$e", e) |
|
|
|
putDebug("${vFile.absolutePath} 解码失败\n$e", e) |
|
|
@ -80,15 +118,22 @@ object ImageProvider { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
*获取bitmap 使用LruCache缓存 |
|
|
|
|
|
|
|
*/ |
|
|
|
fun getImage( |
|
|
|
fun getImage( |
|
|
|
book: Book, |
|
|
|
book: Book, |
|
|
|
src: String, |
|
|
|
src: String, |
|
|
|
width: Int |
|
|
|
width: Int |
|
|
|
): Bitmap { |
|
|
|
): Bitmap { |
|
|
|
|
|
|
|
val cacheBitmap = bitmapLruCache.get(src) |
|
|
|
|
|
|
|
if (cacheBitmap != null) return cacheBitmap |
|
|
|
val vFile = BookHelp.getImage(book, src) |
|
|
|
val vFile = BookHelp.getImage(book, src) |
|
|
|
@Suppress("BlockingMethodInNonBlockingContext") |
|
|
|
@Suppress("BlockingMethodInNonBlockingContext") |
|
|
|
return try { |
|
|
|
return try { |
|
|
|
BitmapUtils.decodeBitmap(vFile.absolutePath, width) |
|
|
|
val bitmap = BitmapUtils.decodeBitmap(vFile.absolutePath, width) |
|
|
|
|
|
|
|
bitmapLruCache.put(src, bitmap) |
|
|
|
|
|
|
|
bitmap |
|
|
|
} catch (e: Exception) { |
|
|
|
} catch (e: Exception) { |
|
|
|
Coroutine.async { |
|
|
|
Coroutine.async { |
|
|
|
putDebug("${vFile.absolutePath} 解码失败\n$e", e) |
|
|
|
putDebug("${vFile.absolutePath} 解码失败\n$e", e) |
|
|
|