zoukankan      html  css  js  c++  java
  • 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 plaincopy
     
    1. Bitmap mBgBitmap = null;  
    2.         mBgBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.unlock_bg);  
    3.         setBackgroundDrawable(new BitmapDrawable(mBgBitmap));  

    这样的好处就是,我们可以保留图片的Bitmap引用mBgBitmap,在我们的VIEW释放时,我们显示的调用

    [java] view plaincopy
     
    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);
    }
    

      

  • 相关阅读:
    Sqlite数据库的加密
    利用Cache缓存数据DataTable数据提高大数据量访问性能
    MYSQL数据库主主同步实战
    【误人子弟】《ASP.NET常用语句120条,(很实用的)
    Debian 添加 FreeBSD 内核支持
    FIREBIRD的基本数据类型
    扩大Portable Ubuntu的系统可用空间
    SQL语句 按年龄段分组统计人数问题
    aspx 页面,master页面与ascx用户控件传值的问题
    MonoDevelop 2.0 Released 发布
  • 原文地址:https://www.cnblogs.com/lee0oo0/p/3290512.html
Copyright © 2011-2022 走看看