加载Drawable图片时出现的oom有关问题
oom问题全称为out of memory (内存溢出),指在加载资源时,资源所占空间超过了应用程序分配的内存空间。
今天在做射击游戏的项目时,加载了20多张图片做了一个animationDrawable动画,预加载动画作为ImageView的background
iv_gun.setBackground(animationDrawable);
结果在一些高分辨率的机器上跑的时候,程序报出OOM错误,在加载背景动画的这一行,在网上找了很多方法,其中一个解决了问题:
点击打开链接
大概意思就是,setBackground方法会根据分辨率的高低重新编码图片,所以有时候会导致图片的大小增大,导致内存溢出
所以解决方法就是新建drawable-nodpi包,并将所有图片放入此包中,然后程序就不会对图片重新进行大小的改变.
----------------------------------------------------------- >>>>>>>>>>>>>>(这里是华丽丽的更新分割线)<<<<<<<<<<<<<<<<<<<<<<<---------------
今天继续做项目的工程中遇到了更为严重的oom问题
因为之后又加入了若干个射击动态效果,所以导致程序运行过程中所占的内存进一步扩大,即使按照上面的那种改变方法也不好使,上网找了很多关于OOM的例子,最终找到了解决方法.
--->
setbackgroundResource()这种方法在设置animationDrawable动画的时候,是会在java层和native层产生两个实例的,而高像素bitmap图是特别占内存的,所以容易产生内存溢出问题,而我找到的最好解决方法是,不适用setBackgroundResource()这个方法而是首先使用decodeStream()这个方法读入bitmap字节码的流,而这个方法与decodeResource等其他方法相比,最好的地方在于它仅仅在native层也就是底层产生一个实例,但不会在java层使用createBitMap()方法产生实例,因此极大地减少了内存的占用,否则当读入20多张大图的时候很容易内存溢出.
下面是decodeStream的用法:
private void loadBitmap(){ BitmapFactory.Options options = new BitmapFactory.Options(); options.inPurgeable=true; options.inInputShareable=true; options.inJustDecodeBounds=false; //设置该属性可获得图片的长宽等信息,但是避免了不必要的提前加载动画 InputStream is=null; for(int i=CLIPID,j=0;i<CLIPID+23&&j<23;i++,j++){ is=getResources().openRawResource(i); //decodestream Bitmap bitmap =BitmapFactory.decodeStream(is, null, options); mbitMap[j]=bitmap; } AnimationDrawable clipDrawable= new AnimationDrawable(); for(int i=0;i<23;i++){ clipDrawable.addFrame(new BitmapDrawable(mbitMap[i]), DURATION); } clip_anim=clipDrawable; }
下面是两张运行时候对heap的检测图,可以明显看出来使用decodeStream方法heap的大小会减半