This commit is contained in:
Horis 2024-02-15 15:56:17 +08:00
parent 9d1aa1c5d6
commit cc99eb1f03
8 changed files with 5 additions and 158 deletions

View File

@ -117,7 +117,6 @@ object PreferKey {
const val welcomeShowIconDark = "welcomeShowIconDark"
const val pageTouchSlop = "pageTouchSlop"
const val showAddToShelfAlert = "showAddToShelfAlert"
const val asyncLoadImage = "asyncLoadImage"
const val ignoreAudioFocus = "ignoreAudioFocus"
const val parallelExportBook = "parallelExportBook"
const val progressBarBehavior = "progressBarBehavior"

View File

@ -460,8 +460,6 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
val showAddToShelfAlert get() = appCtx.getPrefBoolean(PreferKey.showAddToShelfAlert, true)
val asyncLoadImage get() = appCtx.getPrefBoolean(PreferKey.asyncLoadImage, false)
val ignoreAudioFocus get() = appCtx.getPrefBoolean(PreferKey.ignoreAudioFocus, false)
val onlyLatestBackup get() = appCtx.getPrefBoolean(PreferKey.onlyLatestBackup, true)

View File

@ -6,9 +6,7 @@ import android.os.Build
import android.util.Size
import androidx.collection.LruCache
import io.legado.app.R
import io.legado.app.constant.AppLog
import io.legado.app.constant.AppLog.putDebug
import io.legado.app.constant.PageAnim
import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookSource
import io.legado.app.exception.NoStackTraceException
@ -16,10 +14,8 @@ import io.legado.app.help.book.BookHelp
import io.legado.app.help.book.isEpub
import io.legado.app.help.book.isPdf
import io.legado.app.help.config.AppConfig
import io.legado.app.help.coroutine.Coroutine
import io.legado.app.model.localBook.EpubFile
import io.legado.app.model.localBook.PdfFile
import io.legado.app.utils.BitmapCache
import io.legado.app.utils.BitmapUtils
import io.legado.app.utils.FileUtils
import io.legado.app.utils.SvgUtils
@ -70,8 +66,7 @@ object ImageProvider {
) {
//错误图片不能释放,占位用,防止一直重复获取图片
if (oldBitmap != errorBitmap) {
BitmapCache.add(oldBitmap)
//oldBitmap.recycle()
oldBitmap.recycle()
//putDebug("ImageProvider: trigger bitmap recycle. URI: $filePath")
//putDebug("ImageProvider : cacheUsage ${size()}bytes / ${maxSize()}bytes")
}
@ -160,9 +155,8 @@ object ImageProvider {
book: Book,
src: String,
width: Int,
height: Int? = null,
block: (() -> Unit)? = null
): Bitmap? {
height: Int? = null
): Bitmap {
//src为空白时 可能被净化替换掉了 或者规则失效
if (book.getUseReplaceRule() && src.isBlank()) {
book.setUseReplaceRule(false)
@ -174,32 +168,6 @@ object ImageProvider {
//bitmapLruCache的key同一改成缓存文件的路径
val cacheBitmap = getNotRecycled(vFile.absolutePath)
if (cacheBitmap != null) return cacheBitmap
if (height != null && AppConfig.asyncLoadImage && ReadBook.pageAnim() == PageAnim.scrollPageAnim) {
if (asyncLoadingImages.contains(vFile.absolutePath)) {
return null
}
asyncLoadingImages.add(vFile.absolutePath)
Coroutine.async {
BitmapUtils.decodeBitmap(vFile.absolutePath, width, height)
?: SvgUtils.createBitmap(vFile.absolutePath, width, height)
?: throw NoStackTraceException(appCtx.getString(R.string.error_decode_bitmap))
}.onSuccess {
bitmapLruCache.run {
if (maxSize() < maxCacheSize && size() + it.byteCount > maxSize() && putCount() - evictionCount() < 5) {
resize(min(maxCacheSize, maxSize() + it.byteCount))
AppLog.put("图片缓存太小,自动扩增至${(maxSize() / M)}MB。")
}
}
bitmapLruCache.put(vFile.absolutePath, it)
}.onError {
//错误图片占位,防止重复获取
bitmapLruCache.put(vFile.absolutePath, errorBitmap)
}.onFinally {
asyncLoadingImages.remove(vFile.absolutePath)
block?.invoke()
}
return null
}
return kotlin.runCatching {
val bitmap = BitmapUtils.decodeBitmap(vFile.absolutePath, width, height)
?: SvgUtils.createBitmap(vFile.absolutePath, width, height)
@ -214,7 +182,6 @@ object ImageProvider {
fun clear() {
bitmapLruCache.evictAll()
BitmapCache.clear()
}
}

View File

@ -964,9 +964,7 @@ class ReadBookActivity : BaseReadBookActivity(),
*/
override fun pageChanged() {
pageChanged = true
runOnUiThread {
binding.readView.onPageChange()
}
binding.readView.onPageChange()
handler.post {
upSeekBarProgress()
}

View File

@ -32,10 +32,7 @@ data class ImageColumn(
src,
(end - start).toInt(),
height.toInt()
) {
textLine.invalidate()
view.invalidate()
} ?: return
)
val rectF = if (textLine.isImage) {
RectF(start, 0f, end, height)

View File

@ -1,104 +0,0 @@
package io.legado.app.utils
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import java.lang.ref.SoftReference
import java.util.concurrent.ConcurrentHashMap
object BitmapCache {
private val reusableBitmaps: MutableSet<SoftReference<Bitmap>> = ConcurrentHashMap.newKeySet()
fun add(bitmap: Bitmap) {
reusableBitmaps.add(SoftReference(bitmap))
trimSize()
}
fun clear() {
if (reusableBitmaps.isEmpty()) {
return
}
val iterator = reusableBitmaps.iterator()
while (iterator.hasNext()) {
val item = iterator.next().get() ?: continue
item.recycle()
iterator.remove()
}
}
private fun trimSize() {
var byteCount = 0
val iterator = reusableBitmaps.iterator()
while (iterator.hasNext()) {
val item = iterator.next().get() ?: continue
if (byteCount > 128 * 1024 * 1024) {
item.recycle()
iterator.remove()
} else {
byteCount += item.byteCount
}
}
}
fun addInBitmapOptions(options: BitmapFactory.Options) {
// inBitmap only works with mutable bitmaps, so force the decoder to
// return mutable bitmaps.
options.inMutable = true
// Try to find a bitmap to use for inBitmap.
getBitmapFromReusableSet(options)?.also { inBitmap ->
// If a suitable bitmap has been found, set it as the value of
// inBitmap.
options.inBitmap = inBitmap
}
}
private fun getBitmapFromReusableSet(options: BitmapFactory.Options): Bitmap? {
if (reusableBitmaps.isEmpty()) {
return null
}
val iterator = reusableBitmaps.iterator()
while (iterator.hasNext()) {
val item = iterator.next().get() ?: continue
if (item.isMutable) {
// Check to see it the item can be used for inBitmap.
if (canUseForInBitmap(item, options)) {
// Remove from reusable set so it can't be used again.
iterator.remove()
return item
}
} else {
// Remove from the set if the reference has been cleared.
iterator.remove()
}
}
return null
}
private fun canUseForInBitmap(
candidate: Bitmap,
targetOptions: BitmapFactory.Options
): Boolean {
// From Android 4.4 (KitKat) onward we can re-use if the byte size of
// the new bitmap is smaller than the reusable bitmap candidate
// allocation byte count.
val width: Int = targetOptions.outWidth / targetOptions.inSampleSize
val height: Int = targetOptions.outHeight / targetOptions.inSampleSize
val byteCount: Int = width * height * getBytesPerPixel(candidate.config)
return byteCount <= candidate.allocationByteCount
}
/**
* A helper function to return the byte usage per pixel of a bitmap based on its configuration.
*/
private fun getBytesPerPixel(config: Bitmap.Config): Int {
return when (config) {
Bitmap.Config.ARGB_8888 -> 4
Bitmap.Config.RGB_565, Bitmap.Config.ARGB_4444 -> 2
Bitmap.Config.ALPHA_8 -> 1
else -> 1
}
}
}

View File

@ -34,7 +34,6 @@ object BitmapUtils {
BitmapFactory.decodeFileDescriptor(fis.fd, null, op)
op.inSampleSize = calculateInSampleSize(op, width, height)
op.inJustDecodeBounds = false
BitmapCache.addInBitmapOptions(op)
BitmapFactory.decodeFileDescriptor(fis.fd, null, op)
}
}

View File

@ -136,13 +136,6 @@
app:iconSpaceReserved="false"
app:isBottomBackground="true" />
<io.legado.app.lib.prefs.SwitchPreference
android:defaultValue="false"
android:key="asyncLoadImage"
android:title="@string/async_load_image"
app:iconSpaceReserved="false"
app:isBottomBackground="true" />
<io.legado.app.lib.prefs.SwitchPreference
android:defaultValue="false"
android:key="noAnimScrollPage"