加载Drawable图片时出现的oom有关问题

加载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的大小会减半

加载Drawable图片时出现的oom有关问题加载Drawable图片时出现的oom有关问题加载Drawable图片时出现的oom有关问题