android 內存溢出oom錯誤的一些小見解


轉:http://blog.csdn.net/xuhui_7810/article/details/9493681

 

我們在代碼里調用setBackgroundResource(int resid)來設置一個view控件的背景時,如果圖片過大,或者調用setBackgroundResource(int resid)多次時,有可能導致內存溢出.查看代碼:

    public void setBackgroundResource(int resid) {
        if (resid != 0 && resid == mBackgroundResource) {
            return;
        }


        Drawable d= null;
        if (resid != 0) {
            d = mResources.getDrawable(resid);
        }
        setBackgroundDrawable(d);


        mBackgroundResource = resid;
    }

可以發現,背景圖片最后設置為了一個Drawable對象.Drawable對象占用的內存分為java層的和底層的兩部份.JAVA層的內存,如果在你的view釋放時,你的背景圖片調用了Drawable的setCallback(null), 即取消你的背景圖片在VM里的引用,則JAVA這部份的內存空間,在系統調用GC函數時可以把它回收. 但是在native層的內存,GC是釋放不了的.這樣就會導致有內存泄漏. 解決這個問題的辦法有很多種,下面我來說說最簡單的一種:

        設置背景時,不要調用setBackgroundResource(int resid),而改用setBackgroundDrawable(Drawable d) 這個函數,這個函數的參數d 用一個BitmapDrawable new出來.上代碼:

 

[java]  view plain copy
 
  1. Bitmap mBgBitmap = null;  
  2.         mBgBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.unlock_bg);  
  3.         setBackgroundDrawable(new BitmapDrawable(mBgBitmap));  

 

這樣的好處就是,我們可以保留圖片的Bitmap引用mBgBitmap,在我們的VIEW釋放時,我們顯示的調用

 

[java]  view plain copy
 
  1. if(mBgBitmap != null  && !mBgBitmap.isRecycled())  
  2.         {  
  3.             mBgBitmap.recycle();  
  4.             mBgBitmap = null;  
  5.         }     


這段代碼,就可以把native層的內層也給釋放掉,這樣就可以徹底解決內存泄漏的問題

 

加上LruCache效果相比更佳

private LruCache mMemoryCache;

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    // Get memory class of this device, exceeding this amount will throw an
    // OutOfMemory exception.
    final int memClass = ((ActivityManager) context.getSystemService(
            Context.ACTIVITY_SERVICE)).getMemoryClass();

    // Use 1/8th of the available memory for this memory cache.
    final int cacheSize = 1024 * 1024 * memClass / 8;

    mMemoryCache = new LruCache(cacheSize) {
        @Override
        protected int sizeOf(String key, Bitmap bitmap) {
            // The cache size will be measured in bytes rather than number of items.
            return bitmap.getByteCount();
        }
    };
    ...
}

public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
    if (getBitmapFromMemCache(key) == null) {
        mMemoryCache.put(key, bitmap);
    }
}

public Bitmap getBitmapFromMemCache(String key) {
    return mMemoryCache.get(key);
}

  


免責聲明!

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



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