android-内存溢出

2018-03-01  本文已影响0人  舌尖上的Android

android中常见内存溢出原因:
1.数据库的cursor没有关闭。
2.adapter没有缓存/复用contentview
3.调用registerReceiver后没有unregisterReceiver;
4.没有关闭inputstream/outputstream。
5.Bitmap使用后没有调用recycle();
6.Context泄漏
7.读取bitmap对象过大
8.static关键字等。

直接引起内存泄漏:

public class ClassName {  
    private static Context mContext;  
    //省略  
}   
// 如果mContext 被赋值,那么对应的context对象无法被释放,将引起内存泄漏。内存泄漏严重的时候会导致oom

间接引起内存泄漏:

 private static Drawable sBackground;   

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

    TextView label = new TextView(this);  
    label.setText("Leaks are bad");   

    if (sBackground == null) {  
      sBackground = getDrawable(R.drawable.large_bitmap);  
    }  
    label.setBackgroundDrawable(sBackground);   

    setContentView(label);  
  }   
/*虽然并没有显式的保存context的引用,但是drawable与view连接之后,drawable将view设置为一个回调,而view持有context对引用,所以引链如下:
  Drawable->TextView->Context
所以context同样无法释放,最终引起内存泄漏。
*/

内部类持有外部对象引起内存泄漏:

public class BasicActivity extends Activity {  
     @Override  
     public void onCreate(Bundle savedInstanceState) {  
         super.onCreate(savedInstanceState);  
         setContentView(R.layout.main);  
         new MyThread().start();  
     }   

     private class OneThread extends Thread{  
         @Override  
         public void run() {  
             super.run();  
             //do somthing  
         }  
     }  
  }   

由于OneThread 持有外部对象,所以在run函数没有结束时,OneThread不会被销毁,同样外部对象也不会被销毁,因此就出现了内存泄漏的问题。
而AsyncTask的情况会更严重,因为它内部维持了一个线程池,那么AsyncTask产生的thread的声明周期是不稳定的,因此如果AsyncTask作为acitvity的内部类,就更容易出现内存泄漏的问题,所以一般不建议将AsyncTask作为内部类使用。

如何解决:将内部类改为静态内部类,并且内部类中使用弱引用保存Context引用。

bitmap内存泄露解决方法:
及时回收
设置采样率,没有必要全部展示的截取一部分展示
选取合适的分辨率,对图片进行压缩
巧用软引用,防止内存泄漏

其他:
及时关闭InputStream/OutputStream
及时关闭cursor
用registerReceiver()后生命周期结束时调用unregisterReceiver()

上一篇下一篇

猜你喜欢

热点阅读