改进背景图片位图缓存方法。

This commit is contained in:
2025-12-20 18:40:29 +08:00
parent 28d340a772
commit 328f559d2e
3 changed files with 87 additions and 15 deletions

View File

@@ -130,10 +130,11 @@ public class App extends GlobalApplication {
public void onTerminate() {
super.onTerminate();
ToastUtils.release();
// 可选App 终止时清空 Bitmap 缓存,释放内存
if (_mBitmapCacheUtils != null) {
_mBitmapCacheUtils.clearAllCache();
}
}
@Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
}
}

View File

@@ -1,21 +1,22 @@
package cc.winboll.studio.powerbell.utils;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.text.TextUtils;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.powerbell.App;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import cc.winboll.studio.libappbase.LogUtils;
/**
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
* @Date 2025/12/11 01:57
* @Describe 单例 Bitmap 缓存工具类Java 7 兼容)
* 功能:内存缓存 Bitmap支持路径关联缓存、全局获取、缓存清空
* 特点1. 单例模式 2. 压缩加载避免OOM 3. 路径- Bitmap 映射 4. 线程安全
* 功能:内存缓存 Bitmap支持路径关联缓存、全局获取、缓存清空、SP 持久化最后缓存路径、构造时预加载
* 特点1. 单例模式 2. 压缩加载避免OOM 3. 路径-Bitmap 映射 4. 线程安全 5. SP 持久化最后缓存路径 6. 构造时预加载
*/
public class BitmapCacheUtils {
public static final String TAG = "BitmapCacheUtils";
@@ -23,14 +24,24 @@ public class BitmapCacheUtils {
private static final int MAX_WIDTH = 1080;
private static final int MAX_HEIGHT = 1920;
// SP 相关常量
private static final String SP_NAME = "BitmapCacheSP";
private static final String SP_KEY_LAST_CACHE_PATH = "last_cache_image_path";
// 单例实例volatile 保证多线程可见性)
private static volatile BitmapCacheUtils sInstance;
// 路径-Bitmap 缓存容器(内存缓存)
private final Map<String, Bitmap> mBitmapCacheMap;
// SP 实例(用于持久化最后缓存路径)
private final SharedPreferences mSp;
// 私有构造器(单例模式)
private BitmapCacheUtils() {
mBitmapCacheMap = new HashMap<>();
// 初始化 SP使用 App 全局上下文,避免内存泄漏)
mSp = App.getInstance().getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
// 构造时自动预加载 SP 中保存的最后一次缓存路径的图片
preloadLastCachedBitmap();
}
/**
@@ -48,7 +59,7 @@ public class BitmapCacheUtils {
}
/**
* 核心接口:根据图片路径缓存 Bitmap 到内存
* 核心接口:根据图片路径缓存 Bitmap 到内存,并持久化路径到 SP
* @param imagePath 图片绝对路径
* @return 缓存成功的 Bitmap / null路径无效/文件不存在/解码失败)
*/
@@ -70,6 +81,8 @@ public class BitmapCacheUtils {
// 额外校验缓存的Bitmap是否有效
if (cachedBitmap != null && !cachedBitmap.isRecycled()) {
LogUtils.d(TAG, "cacheBitmap: 图片已缓存,直接返回 - " + imagePath);
// 持久化当前路径到 SP更新最后缓存路径
saveLastCachePathToSp(imagePath);
return cachedBitmap;
} else {
// 缓存的Bitmap已失效移除后重新加载
@@ -83,7 +96,9 @@ public class BitmapCacheUtils {
if (bitmap != null) {
// 存入缓存容器
mBitmapCacheMap.put(imagePath, bitmap);
LogUtils.d(TAG, "cacheBitmap: 图片缓存成功 - " + imagePath);
// 持久化当前路径到 SP更新最后缓存路径
saveLastCachePathToSp(imagePath);
LogUtils.d(TAG, "cacheBitmap: 图片缓存成功并持久化路径 - " + imagePath);
} else {
LogUtils.e(TAG, "cacheBitmap: 图片解码失败 - " + imagePath);
}
@@ -109,7 +124,7 @@ public class BitmapCacheUtils {
}
/**
* 清空所有 Bitmap 缓存(释放内存)
* 清空所有 Bitmap 缓存(释放内存),并清空 SP 中保存的最后缓存路径
*/
public void clearAllCache() {
synchronized (mBitmapCacheMap) {
@@ -120,7 +135,9 @@ public class BitmapCacheUtils {
}
mBitmapCacheMap.clear();
}
LogUtils.d(TAG, "clearAllCache: 所有 Bitmap 缓存已清空");
// 清空 SP 中保存的最后缓存路径
clearLastCachePathInSp();
LogUtils.d(TAG, "clearAllCache: 所有 Bitmap 缓存已清空SP 路径已清除");
}
/**
@@ -137,6 +154,12 @@ public class BitmapCacheUtils {
bitmap.recycle();
LogUtils.d(TAG, "removeCachedBitmap: 移除并回收缓存 - " + imagePath);
}
// 若移除的是最后缓存的路径,清空 SP
String lastPath = getLastCachePathFromSp();
if (imagePath.equals(lastPath)) {
clearLastCachePathInSp();
LogUtils.d(TAG, "removeCachedBitmap: 移除的是最后缓存路径,已清空 SP");
}
}
}
@@ -202,5 +225,53 @@ public class BitmapCacheUtils {
}
return inSampleSize;
}
/**
* 从 SP 中获取最后一次缓存的图片路径
* @return 最后缓存的路径 / null未保存
*/
private String getLastCachePathFromSp() {
return mSp.getString(SP_KEY_LAST_CACHE_PATH, null);
}
/**
* 将当前缓存路径持久化到 SP
* @param imagePath 图片绝对路径
*/
private void saveLastCachePathToSp(String imagePath) {
if (TextUtils.isEmpty(imagePath)) {
return;
}
mSp.edit().putString(SP_KEY_LAST_CACHE_PATH, imagePath).commit(); // Java 7 兼容,使用 commit 而非 apply
LogUtils.d(TAG, "saveLastCachePathToSp: 持久化最后缓存路径 - " + imagePath);
}
/**
* 清空 SP 中保存的最后缓存路径
*/
private void clearLastCachePathInSp() {
mSp.edit().remove(SP_KEY_LAST_CACHE_PATH).commit();
LogUtils.d(TAG, "clearLastCachePathInSp: SP 中最后缓存路径已清空");
}
/**
* 构造时预加载 SP 中保存的最后一次缓存路径的图片
*/
private void preloadLastCachedBitmap() {
String lastPath = getLastCachePathFromSp();
if (TextUtils.isEmpty(lastPath)) {
LogUtils.d(TAG, "preloadLastCachedBitmap: SP 中无保存的缓存路径,跳过预加载");
return;
}
// 调用 cacheBitmap 预加载(内部已做文件校验和缓存判断)
Bitmap bitmap = cacheBitmap(lastPath);
if (bitmap != null) {
LogUtils.d(TAG, "preloadLastCachedBitmap: 预加载 SP 中最后缓存路径成功 - " + lastPath);
} else {
LogUtils.w(TAG, "preloadLastCachedBitmap: 预加载 SP 中最后缓存路径失败,清空无效路径 - " + lastPath);
// 预加载失败,清空 SP 中无效路径
clearLastCachePathInSp();
}
}
}