Java-Android加载图片内存优化

Java-Android加载图片内存优化

清晨说ぺ晚安 发布于 2017-06-05 字数 315 浏览 1129 回复 3

请问Android开发加载几张大图片,内存如何优化,不能压缩图片,尝试过压缩,但是效果不能接受。释放资源的工作也做了,每张图都及时释放。网上找的到的优化方法都用了,但是游戏场景多,图片大,在某些手机上还是会崩溃,所以请问有没有其他方面来优化内存。 比如使用另一个进程加载图片、png文件转为其他更省资源的文件格式等。

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

偏爱自由 2017-10-12 3 楼

我对于安卓并不精通,不过我对你们的回答实在看不过去了.刚刚来这个论坛,比较失望.

安卓对于bitmap的大小是由限制的,这个并不是通过所谓的Options就可以解决的,这是安卓内存结构本身的限制!!上述的方法都是扯淡.

要解决图片oom的问题,只能通过建立高效的缓存与图片切割机制来解决.确保只有屏幕显示的view中存在bitmap,或者距离显示事件发生点很近的地方存在bitmap,而其他地方不要保存bitmap对象.

我对bitmap的缓存并不精通,不过我认为,是否可以建立图片持久层,图片jpg或者png格式的btye[]层,bitmap层的三层缓存.三层之间相互转换为上层view提供bitmap的数据.

我写过一些图片显示的程序,感觉在图片总量在20屏幕大小之内时,是安全的.所以对于缓存的性能要求并不是特别高.

ps,不要把一些自己都不知道咋回事的代码就贴上来,真不知道你们是怎么混分的

想挽留 2017-09-15 2 楼

你试用下下面的decodeSampledBitmapFromFile方法,可以根据长宽来处理图片,但是这个不能完全避免不会出现崩溃,但是会有一定的效果:

public static synchronized Bitmap decodeSampledBitmapFromFile(String filename, int reqWidth, int reqHeight, boolean strictInSampleSize) {
try {

// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filename, options);

// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight, strictInSampleSize);

// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;

return BitmapFactory.decodeFile(filename, options);
} catch (Exception e) {
e.printStackTrace();
return null;
} catch (OutOfMemoryError e) {
e.printStackTrace();
System.runFinalizersOnExit(true);
System.exit(0);
return null;
}
}

public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight, boolean strictInSampleSize) {
if (reqWidth <= 0 && reqHeight <= 0) {
return 1;
}
if (options.outWidth <= 0 || options.outHeight <= 0) {
return 1;
}
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;

if (reqWidth <= 0) {
reqWidth = Math.round(((float) width / (float) height) * reqHeight);
} else if (reqHeight <= 0) {
reqHeight = Math.round(((float) height / (float) width) * reqWidth);
}

if (height > reqHeight || width > reqWidth) {
if (width > height) {
inSampleSize = strictInSampleSize ? Math.round((float) height / (float) reqHeight) : height / reqHeight;
} else {
inSampleSize = strictInSampleSize ? Math.round((float) width / (float) reqWidth) : width / reqWidth;
}
if (strictInSampleSize) {
final float totalPixels = width * height;
final float totalReqPixelsCap = reqWidth * reqHeight * 2;
while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
inSampleSize++;
}
}
}
return inSampleSize;
}

虐人心 2017-07-21 1 楼

有看过一个方法,不知道能否合乎需求,貌似 4.0 以上不好用

/**
* 相对不使用选项的 BitmapFactory.decodeFile 来说,可避免内存泄露。
* 需要 API level > 3 才能用 BitmapFactory.Options.inPurgeable 这个变量;
* 另外 inNativeAlloc 是一个隐藏变量,需要使用特殊的方法设置。
*/
public static Bitmap decodeFile(String filePath)
{
Bitmap bitmap = null;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPurgeable = true;

try
{
// [Neo] 可能会有安全异常
BitmapFactory.Options.class.getField("inNativeAlloc").setBoolean(
options, true);
}
catch (Exception e)
{
e.printStackTrace();
}

bitmap = BitmapFactory.decodeFile(filePath, options);
return bitmap;
}

一般情况下,加载图片都是单独起一个线程,把图形都搞到手之后
再写个 handler 给界面,界面在去填充这些 bitmap