1 调整大小
1.1 自动调整:仅该接口decodeResource 是会自动根据dpi和文件放置位置来调整
不同目录下的dpi:(drawble=drawblemdpi=1,其他相应的+0.5)
缩放比例计算公式:scale = (float) targetDensity / density;
Bitmap内存占用公式:像素数据总大小 = 图片宽 x 图片高 x(设备分辨率/资源目录分辨率)² x 每个像素的字节大小,另外强调下,跟图片格式无关,图片格式往往只影响包体积大小
1.2 手动调整:
更改Bitmap.Config格式
通过martix进行压缩(改变Bitmap大小)
采样率压缩(改变Bitmap大小)
2 通过复用
缓存通用的Bitmap对象
如果不进行缓存,尽管看到的是同一张图片文件,但是使用BitmapFactory类的方法来实例化出来的Bitmap,是不同的Bitmap对象。缓存可以避免新建多个Bitmap对象,避免内存的浪费
可以参考源码中的复用方式:
context.getResources().getDrawable,getImage等是有一个全局的hashmap表来缓存的
所以对于一些默认图片,一些头像是可以全局缓存下来(防止泄露,可以用软引用,弱引用)
另外不实例化bitmap而获得宽高的值也是一种方式
ecodeFileDescriptor确实比decodeFile节省内存
推荐统一用decodestream,可以减少中间环节,防止中间商转差价,具体看下下面的一篇博客,写了很多读取方式
通用的图片读取工具类:
BitmapFactory获取Bitmap图片以及解决OOM异常
https://blog.csdn.net/abc6368765/article/details/73800332?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-17-73800332-blog-43058143.235^v43^pc_blog_bottom_relevance_base7&spm=1001.2101.3001.4242.10&utm_relevant_index=20
下面是一些包体积优化:
没有alpha要求的png改为jpg,相当于argb8888 变成rgb565,
还有 WebP(不支持.9)--》更有性价比
索引位图:要rgb565且有ahpe通道,举个例子:
try {
Options options = new Options();
options.inPreferredConfig = Config.RGB_565;
Bitmap bitmap = BitmapFactory.decodeStream(getResources().getAssets().open("index.png"), null, options);
Log.d(TAG, "bitmap.getConfig() = " + bitmap.getConfig());
Log.d(TAG, "scaled bitmap.getByteCount() = " + bitmap.getByteCount());
imageView.setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
是的,自动的优化,所以你只需要确保满足上面两个条件,内存自然下降许多。
3 最后说下 图片内存复用(只是优化了内存分配,而不是减少内存)
主要就是指的复用内存块,不需要在重新给这个bitmap申请一块新的内存,避免了一次内存的分配和回收,从而改善了运行效率
options.inMutable=true;
options.inBitmap=reusable;