视图控件与全局位图缓存类优先调整。

This commit is contained in:
2025-12-11 19:18:02 +08:00
parent 2c77bf775b
commit f240d9c057
3 changed files with 71 additions and 21 deletions

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Thu Dec 11 10:46:09 GMT 2025
#Thu Dec 11 11:14:29 GMT 2025
stageCount=15
libraryProject=
baseVersion=15.12
publishVersion=15.12.14
buildCount=26
buildCount=28
baseBetaVersion=15.12.15

View File

@@ -50,7 +50,7 @@ public class BitmapCacheUtils {
/**
* 核心接口:根据图片路径缓存 Bitmap 到内存
* @param imagePath 图片绝对路径
* @return 缓存成功的 Bitmap / null路径无效/文件不存在)
* @return 缓存成功的 Bitmap / null路径无效/文件不存在/解码失败
*/
public Bitmap cacheBitmap(String imagePath) {
if (TextUtils.isEmpty(imagePath)) {
@@ -59,15 +59,23 @@ public class BitmapCacheUtils {
}
File imageFile = new File(imagePath);
if (!imageFile.exists() || !imageFile.isFile()) {
LogUtils.e(TAG, "cacheBitmap: 图片文件不存在 - " + imagePath);
if (!imageFile.exists() || !imageFile.isFile() || imageFile.length() <= 0) {
LogUtils.e(TAG, "cacheBitmap: 图片文件无效(不存在/非文件/空文件) - " + imagePath);
return null;
}
// 已缓存则直接返回,避免重复加载
if (mBitmapCacheMap.containsKey(imagePath)) {
LogUtils.d(TAG, "cacheBitmap: 图片已缓存,直接返回 - " + imagePath);
return mBitmapCacheMap.get(imagePath);
Bitmap cachedBitmap = mBitmapCacheMap.get(imagePath);
// 额外校验缓存的Bitmap是否有效
if (cachedBitmap != null && !cachedBitmap.isRecycled()) {
LogUtils.d(TAG, "cacheBitmap: 图片已缓存,直接返回 - " + imagePath);
return cachedBitmap;
} else {
// 缓存的Bitmap已失效移除后重新加载
mBitmapCacheMap.remove(imagePath);
LogUtils.w(TAG, "cacheBitmap: 缓存Bitmap已失效移除后重新加载 - " + imagePath);
}
}
// 压缩加载 Bitmap避免OOM
@@ -85,25 +93,33 @@ public class BitmapCacheUtils {
/**
* 核心接口:根据路径获取缓存的 Bitmap
* @param imagePath 图片绝对路径
* @return 缓存的 Bitmap / null
* @return 缓存的有效 Bitmap / null(未缓存/已回收)
*/
public Bitmap getCachedBitmap(String imagePath) {
if (TextUtils.isEmpty(imagePath)) {
return null;
}
return mBitmapCacheMap.get(imagePath);
Bitmap bitmap = mBitmapCacheMap.get(imagePath);
// 校验Bitmap是否有效
if (bitmap != null && bitmap.isRecycled()) {
mBitmapCacheMap.remove(imagePath);
return null;
}
return bitmap;
}
/**
* 清空所有 Bitmap 缓存(释放内存)
*/
public void clearAllCache() {
for (Bitmap bitmap : mBitmapCacheMap.values()) {
if (bitmap != null && !bitmap.isRecycled()) {
bitmap.recycle(); // 主动回收 Bitmap
synchronized (mBitmapCacheMap) {
for (Bitmap bitmap : mBitmapCacheMap.values()) {
if (bitmap != null && !bitmap.isRecycled()) {
bitmap.recycle(); // 主动回收 Bitmap
}
}
mBitmapCacheMap.clear();
}
mBitmapCacheMap.clear();
LogUtils.d(TAG, "clearAllCache: 所有 Bitmap 缓存已清空");
}
@@ -115,22 +131,39 @@ public class BitmapCacheUtils {
if (TextUtils.isEmpty(imagePath)) {
return;
}
Bitmap bitmap = mBitmapCacheMap.remove(imagePath);
if (bitmap != null && !bitmap.isRecycled()) {
bitmap.recycle();
LogUtils.d(TAG, "removeCachedBitmap: 移除并回收缓存 - " + imagePath);
synchronized (mBitmapCacheMap) {
Bitmap bitmap = mBitmapCacheMap.remove(imagePath);
if (bitmap != null && !bitmap.isRecycled()) {
bitmap.recycle();
LogUtils.d(TAG, "removeCachedBitmap: 移除并回收缓存 - " + imagePath);
}
}
}
/**
* 压缩解码 Bitmap按最大尺寸缩放避免OOM
* @param imagePath 图片绝对路径
* @return 解码后的 Bitmap / null文件无效/解码失败)
*/
private Bitmap decodeCompressedBitmap(String imagePath) {
// 前置校验:确保文件有效
File imageFile = new File(imagePath);
if (!imageFile.exists() || !imageFile.isFile() || imageFile.length() <= 0) {
LogUtils.e(TAG, "decodeCompressedBitmap: 文件无效,跳过解码 - " + imagePath);
return null;
}
BitmapFactory.Options options = new BitmapFactory.Options();
// 第一步:只获取图片尺寸,不加载像素
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imagePath, options);
// 校验尺寸是否有效
if (options.outWidth <= 0 || options.outHeight <= 0) {
LogUtils.e(TAG, "decodeCompressedBitmap: 图片尺寸无效 - " + imagePath);
return null;
}
// 计算缩放比例
int sampleSize = calculateInSampleSize(options, MAX_WIDTH, MAX_HEIGHT);
@@ -141,7 +174,15 @@ public class BitmapCacheUtils {
options.inPurgeable = true;
options.inInputShareable = true;
return BitmapFactory.decodeFile(imagePath, options);
try {
return BitmapFactory.decodeFile(imagePath, options);
} catch (OutOfMemoryError e) {
LogUtils.e(TAG, "decodeCompressedBitmap: OOM异常 - " + imagePath);
return null;
} catch (Exception e) {
LogUtils.e(TAG, "decodeCompressedBitmap: 解码异常 - " + imagePath, e);
return null;
}
}
/**

View File

@@ -117,7 +117,7 @@ public class BackgroundView extends RelativeLayout {
// ====================================== 对外方法 ======================================
/**
* 改造后:添加路径判断,路径更新时同步更新缓存
* 改造后:添加路径判断,路径更新时同步更新缓存缓存Bitmap为null时提示并加载透明背景
* @param imagePath 图片绝对路径
*/
public void loadImage(String imagePath) {
@@ -139,8 +139,8 @@ public class BackgroundView extends RelativeLayout {
// ======================== 新增:路径判断逻辑 ========================
// 1. 路径未变化:直接使用缓存
if (imagePath.equals(mCurrentCachedPath)) {
//ToastUtils.show("isReload == false");
Bitmap cachedBitmap = App._mBitmapCacheUtils.getCachedBitmap(imagePath);
// 核心修改判断缓存Bitmap是否为null
if (cachedBitmap != null && !cachedBitmap.isRecycled()) {
LogUtils.d(TAG, "loadImage: 路径未变,使用缓存 Bitmap");
mImageAspectRatio = (float) cachedBitmap.getWidth() / cachedBitmap.getHeight();
@@ -148,7 +148,13 @@ public class BackgroundView extends RelativeLayout {
adjustImageViewSize();
mIvBackground.setVisibility(View.VISIBLE);
return;
}
} else {
// 缓存Bitmap为空或已回收提示并加载透明背景
LogUtils.e(TAG, "loadImage: 全局位图缓存为空或已回收 - " + imagePath);
ToastUtils.show("全局位图缓存为空,无法加载图片");
setDefaultTransparentBackground();
return;
}
}
// 2. 路径已更新:移除旧缓存,加载新图片并更新缓存
@@ -166,6 +172,8 @@ public class BackgroundView extends RelativeLayout {
Bitmap bitmap = decodeBitmapWithCompress(imageFile, 1080, 1920);
if (bitmap == null) {
LogUtils.e(TAG, "loadImage: 图片解码失败");
ToastUtils.show("图片解码失败,无法加载");
setDefaultTransparentBackground();
return;
}
@@ -258,6 +266,7 @@ public class BackgroundView extends RelativeLayout {
mImageAspectRatio = 1.0f;
// 清空缓存路径记录
mCurrentCachedPath = "";
mIvBackground.setVisibility(View.GONE);
}
// ====================================== 重写方法 ======================================