视图控件与全局位图缓存类优先调整。
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
#Created by .winboll/winboll_app_build.gradle
|
#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
|
stageCount=15
|
||||||
libraryProject=
|
libraryProject=
|
||||||
baseVersion=15.12
|
baseVersion=15.12
|
||||||
publishVersion=15.12.14
|
publishVersion=15.12.14
|
||||||
buildCount=26
|
buildCount=28
|
||||||
baseBetaVersion=15.12.15
|
baseBetaVersion=15.12.15
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public class BitmapCacheUtils {
|
|||||||
/**
|
/**
|
||||||
* 核心接口:根据图片路径缓存 Bitmap 到内存
|
* 核心接口:根据图片路径缓存 Bitmap 到内存
|
||||||
* @param imagePath 图片绝对路径
|
* @param imagePath 图片绝对路径
|
||||||
* @return 缓存成功的 Bitmap / null(路径无效/文件不存在)
|
* @return 缓存成功的 Bitmap / null(路径无效/文件不存在/解码失败)
|
||||||
*/
|
*/
|
||||||
public Bitmap cacheBitmap(String imagePath) {
|
public Bitmap cacheBitmap(String imagePath) {
|
||||||
if (TextUtils.isEmpty(imagePath)) {
|
if (TextUtils.isEmpty(imagePath)) {
|
||||||
@@ -59,15 +59,23 @@ public class BitmapCacheUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
File imageFile = new File(imagePath);
|
File imageFile = new File(imagePath);
|
||||||
if (!imageFile.exists() || !imageFile.isFile()) {
|
if (!imageFile.exists() || !imageFile.isFile() || imageFile.length() <= 0) {
|
||||||
LogUtils.e(TAG, "cacheBitmap: 图片文件不存在 - " + imagePath);
|
LogUtils.e(TAG, "cacheBitmap: 图片文件无效(不存在/非文件/空文件) - " + imagePath);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 已缓存则直接返回,避免重复加载
|
// 已缓存则直接返回,避免重复加载
|
||||||
if (mBitmapCacheMap.containsKey(imagePath)) {
|
if (mBitmapCacheMap.containsKey(imagePath)) {
|
||||||
LogUtils.d(TAG, "cacheBitmap: 图片已缓存,直接返回 - " + imagePath);
|
Bitmap cachedBitmap = mBitmapCacheMap.get(imagePath);
|
||||||
return 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)
|
// 压缩加载 Bitmap(避免OOM)
|
||||||
@@ -85,25 +93,33 @@ public class BitmapCacheUtils {
|
|||||||
/**
|
/**
|
||||||
* 核心接口:根据路径获取缓存的 Bitmap
|
* 核心接口:根据路径获取缓存的 Bitmap
|
||||||
* @param imagePath 图片绝对路径
|
* @param imagePath 图片绝对路径
|
||||||
* @return 缓存的 Bitmap / null
|
* @return 缓存的有效 Bitmap / null(未缓存/已回收)
|
||||||
*/
|
*/
|
||||||
public Bitmap getCachedBitmap(String imagePath) {
|
public Bitmap getCachedBitmap(String imagePath) {
|
||||||
if (TextUtils.isEmpty(imagePath)) {
|
if (TextUtils.isEmpty(imagePath)) {
|
||||||
return null;
|
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 缓存(释放内存)
|
* 清空所有 Bitmap 缓存(释放内存)
|
||||||
*/
|
*/
|
||||||
public void clearAllCache() {
|
public void clearAllCache() {
|
||||||
for (Bitmap bitmap : mBitmapCacheMap.values()) {
|
synchronized (mBitmapCacheMap) {
|
||||||
if (bitmap != null && !bitmap.isRecycled()) {
|
for (Bitmap bitmap : mBitmapCacheMap.values()) {
|
||||||
bitmap.recycle(); // 主动回收 Bitmap
|
if (bitmap != null && !bitmap.isRecycled()) {
|
||||||
|
bitmap.recycle(); // 主动回收 Bitmap
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
mBitmapCacheMap.clear();
|
||||||
}
|
}
|
||||||
mBitmapCacheMap.clear();
|
|
||||||
LogUtils.d(TAG, "clearAllCache: 所有 Bitmap 缓存已清空");
|
LogUtils.d(TAG, "clearAllCache: 所有 Bitmap 缓存已清空");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,22 +131,39 @@ public class BitmapCacheUtils {
|
|||||||
if (TextUtils.isEmpty(imagePath)) {
|
if (TextUtils.isEmpty(imagePath)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Bitmap bitmap = mBitmapCacheMap.remove(imagePath);
|
synchronized (mBitmapCacheMap) {
|
||||||
if (bitmap != null && !bitmap.isRecycled()) {
|
Bitmap bitmap = mBitmapCacheMap.remove(imagePath);
|
||||||
bitmap.recycle();
|
if (bitmap != null && !bitmap.isRecycled()) {
|
||||||
LogUtils.d(TAG, "removeCachedBitmap: 移除并回收缓存 - " + imagePath);
|
bitmap.recycle();
|
||||||
|
LogUtils.d(TAG, "removeCachedBitmap: 移除并回收缓存 - " + imagePath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 压缩解码 Bitmap(按最大尺寸缩放,避免OOM)
|
* 压缩解码 Bitmap(按最大尺寸缩放,避免OOM)
|
||||||
|
* @param imagePath 图片绝对路径
|
||||||
|
* @return 解码后的 Bitmap / null(文件无效/解码失败)
|
||||||
*/
|
*/
|
||||||
private Bitmap decodeCompressedBitmap(String imagePath) {
|
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();
|
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||||
// 第一步:只获取图片尺寸,不加载像素
|
// 第一步:只获取图片尺寸,不加载像素
|
||||||
options.inJustDecodeBounds = true;
|
options.inJustDecodeBounds = true;
|
||||||
BitmapFactory.decodeFile(imagePath, options);
|
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);
|
int sampleSize = calculateInSampleSize(options, MAX_WIDTH, MAX_HEIGHT);
|
||||||
|
|
||||||
@@ -141,7 +174,15 @@ public class BitmapCacheUtils {
|
|||||||
options.inPurgeable = true;
|
options.inPurgeable = true;
|
||||||
options.inInputShareable = 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ public class BackgroundView extends RelativeLayout {
|
|||||||
|
|
||||||
// ====================================== 对外方法 ======================================
|
// ====================================== 对外方法 ======================================
|
||||||
/**
|
/**
|
||||||
* 改造后:添加路径判断,路径更新时同步更新缓存
|
* 改造后:添加路径判断,路径更新时同步更新缓存;缓存Bitmap为null时提示并加载透明背景
|
||||||
* @param imagePath 图片绝对路径
|
* @param imagePath 图片绝对路径
|
||||||
*/
|
*/
|
||||||
public void loadImage(String imagePath) {
|
public void loadImage(String imagePath) {
|
||||||
@@ -139,8 +139,8 @@ public class BackgroundView extends RelativeLayout {
|
|||||||
// ======================== 新增:路径判断逻辑 ========================
|
// ======================== 新增:路径判断逻辑 ========================
|
||||||
// 1. 路径未变化:直接使用缓存
|
// 1. 路径未变化:直接使用缓存
|
||||||
if (imagePath.equals(mCurrentCachedPath)) {
|
if (imagePath.equals(mCurrentCachedPath)) {
|
||||||
//ToastUtils.show("isReload == false");
|
|
||||||
Bitmap cachedBitmap = App._mBitmapCacheUtils.getCachedBitmap(imagePath);
|
Bitmap cachedBitmap = App._mBitmapCacheUtils.getCachedBitmap(imagePath);
|
||||||
|
// 核心修改:判断缓存Bitmap是否为null
|
||||||
if (cachedBitmap != null && !cachedBitmap.isRecycled()) {
|
if (cachedBitmap != null && !cachedBitmap.isRecycled()) {
|
||||||
LogUtils.d(TAG, "loadImage: 路径未变,使用缓存 Bitmap");
|
LogUtils.d(TAG, "loadImage: 路径未变,使用缓存 Bitmap");
|
||||||
mImageAspectRatio = (float) cachedBitmap.getWidth() / cachedBitmap.getHeight();
|
mImageAspectRatio = (float) cachedBitmap.getWidth() / cachedBitmap.getHeight();
|
||||||
@@ -148,7 +148,13 @@ public class BackgroundView extends RelativeLayout {
|
|||||||
adjustImageViewSize();
|
adjustImageViewSize();
|
||||||
mIvBackground.setVisibility(View.VISIBLE);
|
mIvBackground.setVisibility(View.VISIBLE);
|
||||||
return;
|
return;
|
||||||
}
|
} else {
|
||||||
|
// 缓存Bitmap为空或已回收,提示并加载透明背景
|
||||||
|
LogUtils.e(TAG, "loadImage: 全局位图缓存为空或已回收 - " + imagePath);
|
||||||
|
ToastUtils.show("全局位图缓存为空,无法加载图片");
|
||||||
|
setDefaultTransparentBackground();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 路径已更新:移除旧缓存,加载新图片并更新缓存
|
// 2. 路径已更新:移除旧缓存,加载新图片并更新缓存
|
||||||
@@ -166,6 +172,8 @@ public class BackgroundView extends RelativeLayout {
|
|||||||
|
|
||||||
Bitmap bitmap = decodeBitmapWithCompress(imageFile, 1080, 1920);
|
Bitmap bitmap = decodeBitmapWithCompress(imageFile, 1080, 1920);
|
||||||
if (bitmap == null) {
|
if (bitmap == null) {
|
||||||
|
LogUtils.e(TAG, "loadImage: 图片解码失败");
|
||||||
|
ToastUtils.show("图片解码失败,无法加载");
|
||||||
setDefaultTransparentBackground();
|
setDefaultTransparentBackground();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -258,6 +266,7 @@ public class BackgroundView extends RelativeLayout {
|
|||||||
mImageAspectRatio = 1.0f;
|
mImageAspectRatio = 1.0f;
|
||||||
// 清空缓存路径记录
|
// 清空缓存路径记录
|
||||||
mCurrentCachedPath = "";
|
mCurrentCachedPath = "";
|
||||||
|
mIvBackground.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ====================================== 重写方法 ======================================
|
// ====================================== 重写方法 ======================================
|
||||||
|
|||||||
Reference in New Issue
Block a user