android 内存溢出解决android开发在大屏手机图片出现内存溢出

解决android开发在大屏手机图片出现内存溢出
说明这个问题,首先来看一下实际的内存占用情况。我们创建一个最简单的android应用,一个Activity,内容是一张图片,图片放在drawable-hdpi目录下。布局文件:图片文件大小145k。打开DDMS,查看内存占用的情况:在米1(小屏手机)上的内存占用情况:而在大屏手机上显示的内存占用情况:内存占用了12M,1-bytearray(byte,boolean)栏中,内存占了8.5M,而最大一个对象占了4.16M,应该就是图片。而实际上图片大小也就145K。之所以大屏手机会出现这种情况,主要是因为我们把图片放在hdpi目录下,而大屏手机实际上是xhdpi甚至是xxhdpi。根据Android官方文档提供的资料:Bydefault,Androidscalesyourbitmapdrawables(.png,.jpg,and.giffiles)andNine-Patchdrawables(.9.pngfiles)sothattheyrenderattheappropriatephysicalsizeoneachdevice.Forexample,ifyourapplicationprovidesbitmapdrawablesonlyforthebaseline,mediumscreendensity(mdpi),thenthesystemscalesthemupwhenonahigh-densityscreen,andscalesthemdownwhenonalow-densityscreen.Android会自动拉伸图片以适应当前手机的分辨率。因此导致了OOM内存溢出。那么如果我们把hdpi的图片复制一份到xhdpi和xxhdpi中会怎样?查看运行的结果:在米1(小屏手机)上的内存占用情况:而在大屏手机上显示的内存占用情况:内存已经有所减少,特别是1-bytearray(byte[],boolean[])这一行。米1由于对应的是hdpi的图片,所以不受影响。但是这样做也有问题,首先我们得把图片都拷贝到不同分辨率对应的目录下(最正确的做法是分别做一套对应分辨率的图片);其次图片占用内存的大小虽然已经减小,但还是太大。再想一想,我们在布局文件里面写android:background和android:src这些属性,实际上解析之后执行的是view.setBackgroundResource和view.setImageResource方法,这两个方法实际上是拿到资源ID再去获取资源的drawable。他们会decode图片后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存。实际上我们可以用decodeStream来替代,因为decodeStream直接调用JNI>>nativeDecodeAsset()来完成decode,无需再使用java层的createBitmap,从而节省了java层的空间.另外我们可以设置图片的参数,例如设置为Bitmap.Config.RGB_565来减少内存开销。因为在android文档中描述Bitmap.Config.RGB_565每一个像素存在2个字节中,而默认的Bitmap.Config.ARGB_8888每一个像素则需要4个字节,理论上足足节省了一半空间。了解这些之后,我把布局文件中的android:background去掉,在java文件中来设置背景。如下:BitmapFactory.Optionsopt=newBitmapFactory.Options();opt.inPreferredConfig=Bitmap.Config.RGB_565;opt.inPurgeable=true;opt.inInputShareable=true;//获取资源图片InputStreamis=context.getResources().openRawResource(resId);Bitmapbitmap=BitmapFactory.decodeStream(is,null,opt);is.close();returnnewBitmapDrawable(context.getResources(),bitmap);运行之后在来看效果:在米1(小屏手机)上的内存占用情况:而在大屏手机上显示的内存占用情况:内存瞬间降下来,1-bytearray(byte[],boolean[])这一行最大值为151K。

本文来自投稿,不代表长河网立场,转载请注明出处: http://www.changhe99.com/a/yBrgV9RG6P.html

(0)

相关推荐