Android開發回收bitmap引發Canvas: trying to use a recycled bitmap錯誤處理


        當你的應用由於加載大量圖片出現OOM異常時,肯定會上網搜索關於OOM的文章,並導求相應的解決方案,比如壓縮圖片大小,或手動回收資源什么的。在這里我們不討論圖片壓縮或緩沖這些方法,而是討論一下手動回收BITMAP時可能出現的問題,亦即 Canvas: trying to use a recycled bitmap。

        很容易可以預料到,你必然會遇到並使用如下代碼:

  1. if(bitmap != null && !bitmap.isRecycled()){  
  2.     bitmap.recycle(); //此句造成的以上異常  
  3.     bitmap = null;  
  4. }  
  5. System.gc();

        然后你將其添加到應用中,用着用着應用崩潰了,查一下LogCat日志,即出現了Canvas: trying to use a recycled bitmap類似的錯誤。

        在進一步探討之前,我們首先要提醒一下:Android本身就有資源回收機制,它的效果並不似他人所說的“不堪入目”,當你的程序運行時出現GC_CONCURRENT_XX時,說明系統正在回收資源。當然,前提是確實存在垃圾(亦即不再會被引用到的資源)。很多時候,你的應用程序出現OOM異常,是因為應用程序可能對大量的BITMAP資源都有引用,ANDROID自然不會去回收你可能會用到的資源,所以這個時候出現OOM是你的應用程序本身有些不完善,不能怪ANDROID。

 

      一般來說,如果代碼已經不再需要使用Bitmap對象了,就可以釋放了。釋放內存以后,就不能再使用該Bitmap對象了,如果再次使用,就會拋出異常。所以一定要保證不再使用的時候釋放。比如,如果是在某個Activity中使用Bitmap,就可以在Activity的onStop()或者onDestroy()方法中進行回收。

     那什么才是“不再需要使用的Bitmap對象”呢?廢話,不就是后面用不到的圖片資源呀,但實際使用的時候,你可能還是會遇到這個異常。其實只要注意BITMAP對象的引用后續是否可能會用到即可,即對象引用的特性

    比如,有同仁在做Android的開發的時候,在ListView 或是 GridView中需要加載大量的圖片,為了避免加載過多的圖片引起OutOfMemory錯誤,設置了一個圖片緩存列表 Map<String, SoftReference<Bitmap>> imageCache , 並對其進行維護,在圖片加載到一定數量的時候,就手動回收掉之前加載圖片的bitmap,如果這個bitmap對象引用還會使用到,就會引起了這個錯誤。

   如下所示:

    public class TextBm{

         private Bitmap bm;

         public void setBitmap(Bitmap bm) {this.bm = bm;}

         public Bitmap getBitmap(){return this.bm;}

   }

    TestBm test_bm = new TestBm();

    test_bm.setBitmap(BitmapFactory.decodeFile(path1));

    //其它更多代碼

    test_bm.setBitmap(BitmapFactory.decodeFile(path2));

      當程序對TestBm的某個實例進行第二次賦值時,由於第一個Bitmap沒有引用到,所以就成為垃圾,這個時候就可以在第二次賦值前用開頭的回收代碼進行回收。這個垃圾也會被ANROID系統自動回收,但不要小看這種垃圾,有些代碼用定時刷新線程來做這樣的賦值,產生很多垃圾,雖然系統能回收掉,但也會消耗很多時間,看看上圖中的pause多少ms就知道了,那就是回收占用的時間。

    再如下所示:

    test_bm.setBitmap(imageCache.get(str1));//從圖片緩存列表中取出1

    //其它更多代碼

    test_bm.setBitmap(imageCache.get(str2));//從圖片緩存列表中取出2

   注意:這里第二次賦值時,第一個是有引用的(或者在更多其它地方使用過的),就是存在imageCache的Map中,如果你也像上面那樣回收,就不是回收test_bm中bm成員的Bitmap1,而是將imageCache中的Bitmap1也給回收了,因為兩個對象是同一個Bitmap1,這樣一旦還有其它地方要使用,就會發生:

Canvas: trying to use a recycled bitmap


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM