一般而言,android中常見的原因主要有以下幾個:
1.數據庫的cursor沒有關閉。
2.構造adapter沒有使用緩存contentview。
3.調用registerReceiver()后未調用unregisterReceiver().
4.未關閉InputStream/OutputStream。
5.Bitmap使用后未調用recycle()。
6.Context泄漏。
7.static關鍵字等。
接下來分別對這些溢出情況說出解決的思路:
1.針對數據庫cursor沒有關閉的情況,如果我們查詢數據庫得到的數據量比較小的話是不會造成內存溢出的,但是如果太大的話就容易發生這種異常,所以當我們在使用完Cursor的時候就應該手動調用它的close方法關閉cursor.
2.針對adapter沒有復用convertView的情況,在我們開發的過程中,經常會遇到一個listview加載成百上千條的數據,如果不復用convertView的話就會在每次執行getView方法的時候都創建一個新的對象,而這個方法的調用速度又是很快的,java不能夠及時的回收內存就會造成OOM異常,這時候除了要在getView方法里面對convertView進行判斷后復用,還應該使用ViewHolder類來保存通過過findViewById得到的子控件地址值.
3.在activity中注冊了廣播,但是在activity退出的時候沒有取消注冊的話可能會造成內存溢出,需要手動的在相應的位置進行反注冊.
4.不關閉輸入輸出流的話就相當於在內存和硬盤一直存在着連接占用着資源,當其他操作需要資源時就會造成內存溢出.
5.位圖在安卓中占用的內存是很大的,使用后如果不及時回收的話會占用大量空間,所以針對位圖的操作一般有如下解決方案:
1)及時的調用resycle方法來手動的回收;
2)設置采樣率,有時候我們不一定要把圖片完全顯示出來,這時候就要按比例來縮放,在我們得到采樣率的時候就可以將圖片縮小后再進行加載,節省大量的內存;
3)使用軟引用.
6.上下文泄露
例如在activity中使用了線程內部類,這時候在線程內存就會保存一個activity的引用,當activity被銷毀的時候,線程仍在執行的話就容易造成oom,因為此時的activity的引用仍然存在沒有被釋放,那么這個activity就仍然沒有從內存中被gc.
7.static關鍵字
開發中使用關鍵字static可以將成員變量和方法變成類變量和類方法,這樣會大大延長變量的生命周期,如果我們過多的使用static來保存占用資源過多的對象的引用就會造成內存溢出,比如用static修飾一個上下文的對象的話.
第一,應該盡量避免static成員變量引用資源耗費過多的實例,比如Context。
第二、Context盡量使用Application Context,因為Application的Context的生命周期比較長,引用它不會出現內存泄露的問題。
第三、使用WeakReference代替強引用。比如可以使用WeakReference<Context> mContextRef;
