优化你的APP--Android内存优化(二)

Android 内存优化(二)


内存使用三大问题

上一篇我们说到内存方面我们主要解决3大问题:内存溢出、内存泄漏和内存抖动。这一篇将针对内存泄漏和内存抖动的优化做介绍。内存分析工具我会单拎出来做介绍的~

对象的内存泄露

发生内存泄漏会导致Memory Generation中的剩余可用Heap Size越来越小,这样会导致频繁触发GC,更进一步引起性能问题。
我们边讲可能出现内存泄漏的原因,边讲其解决的办法。以下会列出可能会出现内存泄漏的原因,大家可以参考来review自己的代码是否有同样的问题出现。

  1. Activity的泄漏
    Activity的泄漏是内存泄漏中最为严重的,Activity占用内存多,影响面也很广(作为上下文传递),我们需要特别注意以下两种情况导致的Activity泄漏:

    • 内部类引用导致Activity的泄漏

      最典型的场景是Handler导致的Activity泄漏,如果Handler中有延迟的任务或者是等待执行的任务队列过长,都有可能因为Handler继续执行而导致Activity发生泄漏。此时的引用关系链是Looper -> MessageQueue -> Message -> Handler -> Activity。为了解决这个问题,可以在UI退出之前,执行remove Handler消息队列中的消息与runnable对象。或者是使用Static + WeakReference的方式来达到断开Handler与Activity之间存在引用关系的目的,Asynctask同样也会出现这样的问题。

    • 上下文Context被传递到其他实例中

      内部类引起的泄漏不仅仅会发生在Activity上,其他任何内部类出现的地方,都需要特别留意!我们可以考虑尽量使用static类型的内部类,同时使用WeakReference的机制来避免因为互相引用而出现的泄露。

    具体弱引用的使用方式可以参考我关于引用的文章1

  2. 使用Application Context而不是Activity Context
    这个很好理解了,Application Context的生命周期会跟随整个App结束而终止,而Activity Context在Activity结束的时候就会结束了,因此就会导致内存泄漏(参考上一条),所以在大多数情况下我们应该使用Application Context,除了指定必须是Activity Context的。例如Dialog。

  3. Bitmap临时对象的回收
    在对Bitmap对象进行缓存或者操作的时候,我们常常会创建一个不小的临时对象,在经过变换得到新的bitmap对象之后,应该尽快回收原始的bitmap,这样可以减小内存压力。
    举个例子来说我们用的比较多的,Bitmap类里面提供的createBitmap()方法。它的描述中告诉我们它会创建一个新的对象或者复制一个资源对象,大小与原始图像相同。所以我们需要回收这个临时对象,在回收的时候需要特别检查source bitmap与return bitmap的引用是否相同,只有在不等的情况下,才能够执行source bitmap的recycle方法。

  4. 注意监听器和广播接收器的注销
    这个不多介绍了,我们在使用广播的时候会有register与unregister方法,如果只注册不注销的话。就会出现下面这个错误提示:

    android.app.IntentReceiverLeaked:Activity XXXXXXXX has leaked IntentReceiver XXXXXXXX that was originally registered here. Are you missing a call to unregisterReceiver()?

    我们应该在对应的生命周期里进行注册和注销,以确保我们所使用的ListenerBroadcast不会出现内存泄漏。

  5. Webview的泄漏
    Android的Webview存在很大的兼容性问题,从以前的webkit内核到现在的chrome内核,不同的Android系统版本对Webview的影响也不一样,而且每个手机厂商自己的ROM里的Webview也存在很大的差异。具体的问题看这里WebView causes memory leak - leaks the parent Activity。所以建议把Webview放到一个独立进程之中进行操作,通过AIDL来进程间通信,当Webview执行的业务完成之后,我们就可以进行销毁从而完整释放内存。

  6. Cursor对象及时关闭
    如果这些Cursor对象反复多次的出现而不关闭,对内存管理产生很大的影响。你有可能因此遇到OOM也有可能是数据库无法继续操作,这两个结果都不是我们想看到的,所以使用完Cursor对象一定要及时关闭

内存抖动

大家可能很少听到这个名词,它是什么原因导致的呢?内存抖动字面上很好理解,就是短时间内大量的出现对象创建和回收。
通过Android Studio中的Android Monitor中的Monitor Memory来观察可以发现,当出现内存抖动的时候会出现如下图这样的情况:
这里写图片描述
此种问题大多数出现在循环或者重复调用的回调里,例如for循环分配占内存的对象,自定义view里面的OnDraw方法等等。
所以我们应该避免这些问题,尽量在for循环体外创捷对象或者使用对象池等方法,但也需要注意对象池的内存管理和释放。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值