【性能优化】内存泄漏知多少

833 阅读2分钟

其中内存泄漏产生的原因在Android中大致分为以下几种:

  • 单例(由于单例是全局的,生命周期跟app一样长,如static成员引用activity)

  • 静态变量(静态集合对象强引用没有清理)

  • 匿名内部类/非静态内部类(由于内部类会持有外部类的引用,解决方法是改成静态内部类和使用弱引用)

  • 资源未关闭(cursor,file,bitmap)

  • 接收器或监听器注册没有取消(broadcastReceiver,eventbus)

  • handler 由于在Handler的使用中,handler会发送message对象到 MessageQueue中 然后 Looper会轮询MessageQueue 然后取出Message执行,但是如果一个Message长时间没被取出执行,那么由于 Message中有 Handler的引用,而 Handler 一般来说也是内部类对象,Message引用 Handler ,Handler引用 Activity 这样 使得 Activity无法回收。

    解决办法:改成静态内部类和使用弱引用,并且在onDestory()时调用removeCallbacksAndMessages()清空消息队列中所有消息。

注意

1.动态广播注册

@Override
 protected void onResume(){
   super.onResume();

  //实例化BroadcastReceiver子类 & IntentFilter
   mBroadcastReceiver mBroadcastReceiver = new mBroadcastReceiver();
   IntentFilter intentFilter = new IntentFilter();

  //设置接收广播的类型
   intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE);

  //调用Context的registerReceiver()方法进行动态注册
   registerReceiver(mBroadcastReceiver, intentFilter);
 }


//注册广播后,要在相应位置记得销毁广播
//即在onPause() 中unregisterReceiver(mBroadcastReceiver)
//当此Activity实例化时,会动态将MyBroadcastReceiver注册到系统中
//当此Activity销毁时,动态注册的MyBroadcastReceiver将不再接收到相应的广播。
 @Override
 protected void onPause() {
   super.onPause();
   //销毁在onResume()方法中的广播
   unregisterReceiver(mBroadcastReceiver);
   }
}

在onResume()注册、onPause()注销是因为onPause()在App死亡前一定会被执行,从而保证广播在App死亡前一定会被注销,从而防止内存泄露。

1.不在onCreate() & onDestory() 或 onStart() & onStop()注册、注销是因为: 当系统因为内存不足(优先级更高的应用需要内存,请看上图红框)要回收Activity占用的资源时,Activity在执行完onPause()方法后就会被销毁,有些生命周期方法onStop(),onDestory()就不会执行。当再回到此Activity时,是从onCreate方法开始执行。