改进背景图片位图缓存方法。
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
#Created by .winboll/winboll_app_build.gradle
|
#Created by .winboll/winboll_app_build.gradle
|
||||||
#Sat Dec 20 09:38:35 GMT 2025
|
#Sat Dec 20 10:26:46 GMT 2025
|
||||||
stageCount=10
|
stageCount=10
|
||||||
libraryProject=
|
libraryProject=
|
||||||
baseVersion=15.14
|
baseVersion=15.14
|
||||||
publishVersion=15.14.9
|
publishVersion=15.14.9
|
||||||
buildCount=76
|
buildCount=81
|
||||||
baseBetaVersion=15.14.10
|
baseBetaVersion=15.14.10
|
||||||
|
|||||||
@@ -130,10 +130,11 @@ public class App extends GlobalApplication {
|
|||||||
public void onTerminate() {
|
public void onTerminate() {
|
||||||
super.onTerminate();
|
super.onTerminate();
|
||||||
ToastUtils.release();
|
ToastUtils.release();
|
||||||
// 可选:App 终止时清空 Bitmap 缓存,释放内存
|
|
||||||
if (_mBitmapCacheUtils != null) {
|
|
||||||
_mBitmapCacheUtils.clearAllCache();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTrimMemory(int level) {
|
||||||
|
super.onTrimMemory(level);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,22 @@
|
|||||||
package cc.winboll.studio.powerbell.utils;
|
package cc.winboll.studio.powerbell.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import cc.winboll.studio.libappbase.LogUtils;
|
||||||
|
import cc.winboll.studio.powerbell.App;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import cc.winboll.studio.libappbase.LogUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
* @Author ZhanGSKen&豆包大模型<zhangsken@qq.com>
|
||||||
* @Date 2025/12/11 01:57
|
* @Date 2025/12/11 01:57
|
||||||
* @Describe 单例 Bitmap 缓存工具类(Java 7 兼容)
|
* @Describe 单例 Bitmap 缓存工具类(Java 7 兼容)
|
||||||
* 功能:内存缓存 Bitmap,支持路径关联缓存、全局获取、缓存清空
|
* 功能:内存缓存 Bitmap,支持路径关联缓存、全局获取、缓存清空、SP 持久化最后缓存路径、构造时预加载
|
||||||
* 特点:1. 单例模式 2. 压缩加载避免OOM 3. 路径- Bitmap 映射 4. 线程安全
|
* 特点:1. 单例模式 2. 压缩加载避免OOM 3. 路径-Bitmap 映射 4. 线程安全 5. SP 持久化最后缓存路径 6. 构造时预加载
|
||||||
*/
|
*/
|
||||||
public class BitmapCacheUtils {
|
public class BitmapCacheUtils {
|
||||||
public static final String TAG = "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_WIDTH = 1080;
|
||||||
private static final int MAX_HEIGHT = 1920;
|
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 保证多线程可见性)
|
// 单例实例(volatile 保证多线程可见性)
|
||||||
private static volatile BitmapCacheUtils sInstance;
|
private static volatile BitmapCacheUtils sInstance;
|
||||||
// 路径-Bitmap 缓存容器(内存缓存)
|
// 路径-Bitmap 缓存容器(内存缓存)
|
||||||
private final Map<String, Bitmap> mBitmapCacheMap;
|
private final Map<String, Bitmap> mBitmapCacheMap;
|
||||||
|
// SP 实例(用于持久化最后缓存路径)
|
||||||
|
private final SharedPreferences mSp;
|
||||||
|
|
||||||
// 私有构造器(单例模式)
|
// 私有构造器(单例模式)
|
||||||
private BitmapCacheUtils() {
|
private BitmapCacheUtils() {
|
||||||
mBitmapCacheMap = new HashMap<>();
|
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 图片绝对路径
|
* @param imagePath 图片绝对路径
|
||||||
* @return 缓存成功的 Bitmap / null(路径无效/文件不存在/解码失败)
|
* @return 缓存成功的 Bitmap / null(路径无效/文件不存在/解码失败)
|
||||||
*/
|
*/
|
||||||
@@ -70,6 +81,8 @@ public class BitmapCacheUtils {
|
|||||||
// 额外校验缓存的Bitmap是否有效
|
// 额外校验缓存的Bitmap是否有效
|
||||||
if (cachedBitmap != null && !cachedBitmap.isRecycled()) {
|
if (cachedBitmap != null && !cachedBitmap.isRecycled()) {
|
||||||
LogUtils.d(TAG, "cacheBitmap: 图片已缓存,直接返回 - " + imagePath);
|
LogUtils.d(TAG, "cacheBitmap: 图片已缓存,直接返回 - " + imagePath);
|
||||||
|
// 持久化当前路径到 SP(更新最后缓存路径)
|
||||||
|
saveLastCachePathToSp(imagePath);
|
||||||
return cachedBitmap;
|
return cachedBitmap;
|
||||||
} else {
|
} else {
|
||||||
// 缓存的Bitmap已失效,移除后重新加载
|
// 缓存的Bitmap已失效,移除后重新加载
|
||||||
@@ -83,7 +96,9 @@ public class BitmapCacheUtils {
|
|||||||
if (bitmap != null) {
|
if (bitmap != null) {
|
||||||
// 存入缓存容器
|
// 存入缓存容器
|
||||||
mBitmapCacheMap.put(imagePath, bitmap);
|
mBitmapCacheMap.put(imagePath, bitmap);
|
||||||
LogUtils.d(TAG, "cacheBitmap: 图片缓存成功 - " + imagePath);
|
// 持久化当前路径到 SP(更新最后缓存路径)
|
||||||
|
saveLastCachePathToSp(imagePath);
|
||||||
|
LogUtils.d(TAG, "cacheBitmap: 图片缓存成功并持久化路径 - " + imagePath);
|
||||||
} else {
|
} else {
|
||||||
LogUtils.e(TAG, "cacheBitmap: 图片解码失败 - " + imagePath);
|
LogUtils.e(TAG, "cacheBitmap: 图片解码失败 - " + imagePath);
|
||||||
}
|
}
|
||||||
@@ -109,7 +124,7 @@ public class BitmapCacheUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清空所有 Bitmap 缓存(释放内存)
|
* 清空所有 Bitmap 缓存(释放内存),并清空 SP 中保存的最后缓存路径
|
||||||
*/
|
*/
|
||||||
public void clearAllCache() {
|
public void clearAllCache() {
|
||||||
synchronized (mBitmapCacheMap) {
|
synchronized (mBitmapCacheMap) {
|
||||||
@@ -120,7 +135,9 @@ public class BitmapCacheUtils {
|
|||||||
}
|
}
|
||||||
mBitmapCacheMap.clear();
|
mBitmapCacheMap.clear();
|
||||||
}
|
}
|
||||||
LogUtils.d(TAG, "clearAllCache: 所有 Bitmap 缓存已清空");
|
// 清空 SP 中保存的最后缓存路径
|
||||||
|
clearLastCachePathInSp();
|
||||||
|
LogUtils.d(TAG, "clearAllCache: 所有 Bitmap 缓存已清空,SP 路径已清除");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -137,6 +154,12 @@ public class BitmapCacheUtils {
|
|||||||
bitmap.recycle();
|
bitmap.recycle();
|
||||||
LogUtils.d(TAG, "removeCachedBitmap: 移除并回收缓存 - " + imagePath);
|
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;
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user