Android性能——内存溢出(篇三:内存溢出的解决办法)

7 篇文章 0 订阅
2 篇文章 0 订阅

解决内存溢出的方法大体如下几种:

一:在内存引用上做些处理,常用的有软引用、强化引用、弱引用 应用的强弱顺序是强、软、弱、和虚。 软引用是主要用于内存敏感的高速缓存。在jvm报告内存不足之前会清除所有的软引用,这样以来gc就有可能收集软可及的对象,可能解决内存吃紧问题,避免内存溢出。

二:减小对象的内存占用 使用更加轻量的数据结构,SparseArray替代HashMap。 因为使用HashMap时,即使你只设置了一个基本数据类型的键,比如说int,但是也会按照对象的大小来分配内存,大概是32字节,而不是4字节,因此最好使用优化后的数据集合 任何一个Java类,包括匿名类、内部类,都要占用大概500字节的内存空间,任何一个类的实例要消耗12-16字节的内存开支,因此频繁创建实例也是会在一定程序上影响内存的。 比如自定义View的onDraw方法,会频繁的执行,所以最好不要在里面过多的创建实例 避免在Android里面使用Enum,枚举通常会比使用静态常量消耗两倍以上的内存,尽可能不使用枚举 图像(在内存中加载图片时直接在内存中做处理,如:边界压缩) 缓存图像到内存,采用软引用缓存到内存,而不是在每次使用的时候都从新加载到内存; 调整图像大小,手机屏幕尺寸有限,分配给图像的显示区域本身就更小,有时图像大小可以做适当调整; options.inSampleSize = Util.computeSampleSize(options, 600, (int) (1 * 1024 * 1024)); 采用低内存占用量的编码方式,比如Bitmap.Config.ARGB_4444比Bitmap.Config.ARGB_8888更省内存; options.inPreferredConfig = Bitmap.Config.ARGB_8888; 及时回收图像,如果引用了大量Bitmap对象,而应用又不需要同时显示所有图片,可以将暂时用不到的Bitmap对象及时回收掉; bitmap.recycle(); 自定义堆内存分配大小,优化Dalvik虚拟机的堆内存分配;

三:注意对象的引用释放

四:动态回收内存 内存对象的重复利用

五:优化Dalvik虚拟机的堆内存分配 对于Android平台来说,其托管层使用的Dalvik JavaVM从目前的表现来看还有很多地方可以优化处理,比如我们在开发一些大型游戏或耗资源的应用中可能考虑手动干涉GC处理,使用 dalvik.system.VMRuntime类提供的 在程序oncreate中调用VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION); setTargetHeapUtilization方法可以增强程序堆内存的处理效率。

六:自定义堆内存大小 private final static int CWJ_HEAP_SIZE = 6* 1024* 1024 ; //设置最小heap内存为6MB大小 VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE);

七:慎用三方sdk

 

——释放对象的引用

方法0 : 单个页面,横竖屏切换N次后 OOM        

 1. 看看页面布局当中有没有大的图片,比如背景图之类的。去除xml中相关设置,改在程序中设置背景图(放在onCreate()方法中):           Drawable bg = getResources().getDrawable(R.drawable.bg);           XXX.setBackgroundDrawable(rlAdDetailone_bg);           在Activity destory时注意,bg.setCallback(null); 防止Activity得不到及时的释放          

 2. 跟上面方法相似,直接把xml配置文件加载成view 再放到一个容器里,然后直接调用 this.setContentView(View view);方法            避免xml的重复加载

方法1 :  等比例缩小图片                  

InputStream is = this.getResources().openRawResource(R.drawable.pic1);                 BitmapFactory.Options options = new BitmapFactory.Options();                 options.inSampleSize = 4;                  Bitmap btp =BitmapFactory.decodeStream(is,null,options)

方法2 :  对图片采用软引用,及时地进行recyle()操作                  

SoftReference<Bitmap> bitmap;                 bitmap = new SoftReference<Bitmap>(pBitmap);     if(bitmap != null){               if(bitmap.get() != null && !bitmap.get().isRecycled()){                 bitmap.get().recycle();                 bitmap = null;             }         }

方法3: 尽量不要使用setImageBitmap或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中配置相应的图片资源, 否则在不同分辨率机器上都是同样大小(像素点数量),显示出来的大小就不对了。

方法4 :  对复杂的listview进行合理设计与编码:               注意重用Adapter里面的 convertView  以及holder机制的运用   ----- 参考资料: api demo list 14. Efficient Adapter

1. listview有对当前显示的 convertView  进行缓存。

2. ViewHolder指构造一个ViewHolder类,把listview每一条需要显示的内容view的子view列出来。

 public View getView(int position, View convertView, ViewGroup parent) {  if (convertView == null) {             v = mInflater.inflate(resource, parent, false);             final int[] to = mTo;             final int count = to.length;             final View[] holder = new View[count];             for (int i = 0; i < count; i++) {                 holder[i] = v.findViewById(to[i]);             }             v.setTag(holder);         } else {         } }

方法5 : 在页面切换时尽可能少地重复使用一些代码,比如:重复调用数据库,反复使用某些对象等等......

方法6 :Android堆内存也可自己定义大小 和  优化Dalvik虚拟机的堆内存分配  

Android应用程序的默认最大内存值为16M. 修改应用程序的默认最大内存有2种方法: 1、修改代码,适用于自己编译烧机: 当应用程序分配内存时,会调用到dalvik/vm/alloc/HeapSource.c中的 dvmTrackExternalA

llocation()方法,继而调用到externalAllocPossible()方法,该方法要求当前堆已使用的大小(由currentHeapSize和hs->externalBytesAllocated构成)加上我们需要再次分配的内存大小不能超过堆的最大内存值,如果超过就会报错。 有两个地方决定了一个堆的最大内存: 1)dalvik/vm/Init.c中的 gDvm.heapSizeMax = 16 * 1024 * 1024;    // Spec says 75% physical mem 2)frameworks/base/core/jni/AndroidRuntime.cpp中的 property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m"); 因此解决办法就是将以上2点中默认的16M改大一点,譬如32M。

2、修改配置文件,适用于烧机后的版本。 修改或添加/system/build.prop中的配置项: dalvik.vm.heapsize=32m        

3、注意若使用这种方法:project build target 只能选择 <= 2.2 版本,否则编译将通不过。 所以不建议用这种方式    

private final static int CWJ_HEAP_SIZE= 6*1024*1024;     private final static float TARGET_HEAP_UTILIZATION = 0.75f;     VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE);   VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION);

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值