一:BitmapFactory.decodeResource 与 decodeStream
android应用加载本地大图(res资源文件或者sdcard外部文件)时,经常容易出现内存溢出问题.
常见使用错误如,开发应用的滑动引导页面时,使用ViewPager加载了几张res资源中的大图,在部分低配置机型上会出现OOM错误.
错误如下图所示:
问题分析:
ImageView的setImageBitmap、setImageResource或者BitmapFactory.decodeResource,这些函数调用,完成decode之后,
最终都是通过Java层的createBitmap来完成的,需要消耗更多内存.
解决办法是,使用BitmapFactory.decodeStream(InputStream is, Rect outPadding, Options opts)方法,创建出一个Bitmap对象,
再使用setImageBitmap方法赋值到ImageView控件上.
decodeStream最大的秘密在于其直接调用JNIdecodeStream最大的秘密在于其直接调用JNI>>nativeDecodeAsset()来完成decode,无需再使用java层的
createBitmap,从而节省了java层的空间.
如果在读取时加上图片的Config参数,可以跟有效减少加载的内存,从而跟有效阻止抛out of Memory异常.
另外,decodeStream直接拿的图片来读取字节码了,不会根据机器的各种分辨率来自动适应,使用了decodeStream之后,
需要在hdpi和mdpi,ldpi中配置相应的图片资源,否则在不同分辨率机器上都是同样大小(像素点数量),显示就不正常啦.
解决代码:
inPurgeable如果设置为true,则由此产生的位图将分配其像素,以便系统需要回收内存时可以将它们清除;/** * 以最省内存的方式读取本地资源的图片 * @param context * @param resId * @return */ public static Bitmap readBitMap(Context context, int resId){ BitmapFactory.Options opt = new BitmapFactory.Options(); opt.inPreferredConfig = Config.RGB_565; opt.inPurgeable = true; opt.inInputShareable = true; InputStream is = context.getResources().openRawResource(resId); return BitmapFactory.decodeStream(is,null,opt); }
inInputShareable与inPurgeable一起使用,如果inPurgeable为false那该设置将被忽略,如果为true,
那么它可以决定位图是否能够共享一个指向数据源的引用,或者是进行一份拷贝.
的的