android开发内存泄露分析

内存泄露分析:

在android开发的项目中,内存泄露是影响产品稳定性的最大诱因,目前总结到的内存泄露的2大源头如下:


1.Bitmap内存未被释放

Bitmap内存泄露是所有原因中最严重的一个,因为Bitmap对象引用的内存分JAVA层和C层,而GC机制在一般情况下只会回收JAVA层的Bitmap资源,所以必须要调用Bitmap.recycle()方法去主动回收C层的内存,防止内存泄露。然而,这里的recycle也是有个前提条件的,从android官方文档可以看到以下说明:

Free the native object associated with this bitmap, and clear the reference to the pixel data. This will not free the pixel data synchronously; it simply allows it to be garbage collected if there are no other references. The bitmap is marked as "dead", meaning it will throw an exception if getPixels() or setPixels() is called, and will draw nothing. This operation cannot be reversed, so it should only be called if you are sure there are no further uses for the bitmap. This is an advanced call, and normally need not be called, since the normal GC process will free up this memory when there are no more references to this bitmap.

大意是:释放于bitmap对象相关联的本地对象资源(即C层),清除像素数据的引用,但这不是同步的操作。这仅是允许GC去把这些对象资源标记为“dead‘状态,而且此操作是不可逆转的,最重要的是,只有在bitmap对象未被任何直接或间接引用时,才真正地被GC释放内存。

解决方法:及时调用bitmap.recycle()方法,并必须确保bitmap对象不被任何对象引用



2.handler.sendMessageDelayed()造成内存泄露

(声明:eoe文章著作权属于作者,受法律保护,转载时请务必以超链接形式附带如下信息,原作者:花_开_堪_折_枝

(1)当Android程序第一次创建的时候,在主线程同时会创建一个Looper对象。Looper实现了一个简单的消息队列,一个接着一个处理Message对象。程序框架所有主要的事件(例如:屏幕上的点击时间,Activity生命周期的方法等等)都包含在Message对象中,然后添加到Looper的消息队列中,一个一个处理。主线程的Looper存在整个应用程序的生命周期内。

(2)当一个Handler对象在主线程中创建的时候,它会关联到Looper的 message queue 。Message添加到消息队列中的时候Message会持有当前Handler引用,当Looper处理到当前消息的时候,会调用Handler#handleMessage(Message).

(3)在java中,no-static的内部类会 隐式的 持有当前类的一个引用。static的类则没有。

下面代码就是造成泄露的例子:

public class SampleActivity extends Activity {

  private final Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
      // ...
    }
  }

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // 发送一个10分钟后执行的一个消息
    mHandler.sendMessageDelayed(MSG_TEST, 600000);

    // 结束当前的Activity
    finish();
  }
}


解决方法一:弱引用静态内部类Handler,避免当前对象引用和内存驻留

public class SampleActivity extends Activity {

  /**
   * 使用静态的内部类,不会持有当前对象的引用
   */
  private static class MyHandler extends Handler {
    private final WeakReference<SampleActivity> mActivity;

    public MyHandler(SampleActivity activity) {
      mActivity = new WeakReference<SampleActivity>(activity);
    }

    @Override
    public void handleMessage(Message msg) {
      SampleActivity activity = mActivity.get();
      if (activity != null) {
        // ...
      }
    }
  }

  private final MyHandler mHandler = new MyHandler(this);

  /**
   * 使用静态的内部类,不会持有当前对象的引用
   */

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    //  发送一个10分钟后执行的一个消息
    mHandler.sendMessageDelayed(MSG_TEST, 600000);//自定义消息

    // 结束
    finish();
  }
}


解决方法二:Activity销毁前,移除延迟消息

@Override
  protected void onDestroy(Bundle savedInstanceState) {
    //  Activity销毁时移除在队列中的消息
    mHandler.removeMessages(MSG_TEST));
    super.onDestroy();
  }


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值