Failed to allocate a 74649612 byte allocation with 16777216 free bytes and 70MB until OOM
com.wcyq.gangrong.ui.activity.NewGuideActivity$GuidPagerAdapter.instantiateItem(NewGuideActivity.java:105)
之前测试公司的测试机测试一直也没有出现这种问题.
通过bugly 捕捉到了这个错误;
市面上的解决办法,我所知道的有两种:
第一种,弃用
imageView.setImageResource(resId)
采用图片加载框架进行加载,解决内存溢出和卡顿问题:
代码如下:
Glide.with(mContext).load(resId).placeholder(resId).diskCacheStrategy(DiskCacheStrategy.RESULT).into(imageView);
或者:
app.imageLoader.displayImage(
imageUrls.get(i), imageView, Utils.setImageLoaderImg(R.drawable.pic_launchpage_fail,R.drawable.pic_launchpage,0));
第二种方式: 自己对图片先进行网络在线压缩,第二把png转化为jpg,同样的图片 png 要比jpg的大很多
然后,自行对设置图片格式RGB-565
然后隔行取点, 减少内存中的图片大小
如下:
@Override
protected void onStop() {
super.onStop();
if (btp!=null){
btp.recycle();
}
}
/**
* 大图片处理机制
* 利用Bitmap 转存 R图片
*/
public static Bitmap btp;
public void getBitmapForImgResourse(Context mContext, int imgId, ImageView mImageView) throws IOException {
InputStream is = mContext.getResources().openRawResource(imgId);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = false;
options.inPreferredConfig = Bitmap.Config.RGB_565;
options.inPurgeable = true;
options.inInputShareable = true;
options.inSampleSize = 1;
btp = BitmapFactory.decodeStream(is, null, options);
mImageView.setImageBitmap(btp);
// btp.recycle();
is.close();
}
备注:
那是为什么,会导致oom呢:
原来当使用像 imageView.setBackgroundResource,imageView.setImageResource, 或者 BitmapFactory.decodeResource 这样的方法来设置一张大图片的时候,
这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存。
因此,改用先通过BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView的 source,decodeStream最大的秘密在于其直接调用JNI>>nativeDecodeAsset()来完成decode,无需再使用java层的createBitmap,从而节省了java层的空间。如果在读取时加上图片的Config参数,可以跟有效减少加载的内存,从而跟有效阻止抛out of Memory异常。
另外,需要特别注意:
decodeStream是直接读取图片资料的字节码了, 不会根据机器的各种分辨率来自动适应,使用了decodeStream之后,需要在hdpi和mdpi,ldpi中配置相应的图片资源,否则在不同分辨率机器上都是同样大小(像素点数量),显示出来的大小就不对了。
延伸:
options.inSampleSize = 2;的意思是什么
这个是读取bitmap时用到的属性,是为了对原图降采样. 比如原图是一个 4000 * 4000 点阵的图,占用内存就是 4000 * 4000 * 单个像素占用字节数 单个像素占用字节数取决于你用的是 RGB565, ARGB8888 等. 4000 * 4000 这个解析度已很接近目前市面主流机器的默认照片解析度. 假设你用的是RGB565解析这张图,那一个点就占用2个字节.如果完整解析这个图片,就需要 大约3.2MB的内存. 如果你用了一个GridView,同时显示了30张这种图,那几乎可以确定你会收到一个OOM异常. 所以需要对这种大图进行降采样,以减小内存占用.毕竟拇指大小的地方根本用不着显示那么高的解析度. 因为直接从点阵中隔行抽取最有效率,所以为了兼顾效率, inSampleSize 这个属性只认2的整数倍为有效. 比如你将 inSampleSize 赋值为2,那就是每隔2行采1行,每隔2列采一列,那你解析出的图片就是原图大小的1/4. 这个值也可以填写非2的倍数,非2的倍数会被四舍五入. 综上,用这个参数解析bitmap就是为了减少内存占用.