您的位置:首页 > 移动开发 > Android开发

Android 图片加载导致内存占用过大的问题

2014-02-28 21:54 309 查看
Android经常出现的OOM就是因为加载的图片过多没有及时回收,所以造成占用的内存过大,接下来就OOM了.下面是转载,得到的启示:不要乱设置背景图了...

--------------------------------------------------------------   分割线  -------------------------------------------------------

android3.0默认heap size为48m,进入ddms,在ddms中“update heap”-“cause gc”,查看应用的内存使用情况,发现每进入一个activity,1-byte array(byte[], boolean[])的值总是会相应的增加,到最后一个activity的时候啥都不干,heap
size已经快30m了。通过分析,1-byte array就是bitmap的占用空间,这就说明不断有新的bitmap在内存中。由于ui使用了很多图片,比如大背景图,按钮图片等等,看来是这些图片 都会存在内存中,即使当前activity已经销毁进入下一个activity,前一个activity的图片资源也没有销毁。
其中一个做法是:

用Bitmap bm = BitmapFactory.decodeResource(this.getResources(), R.drawable.splash);

BitmapDrawable bd = new BitmapDrawable(this.getResources(), bm);

mBtn.setBackgroundDrawable(bd);

来代替mBtn.setBackgroundResource(R.drawable.splash)。

销毁的时候使用:

BitmapDrawable bd = (BitmapDrawable)mBtn.getBackground();

mBtn.setBackgroundResource(0);//别忘了把背景设为null,避免onDraw刷新背景时候出现used a recycled bitmap错误

bd.setCallback(null);

bd.getBitmap().recycle();
因为setBackgroundResource时,会缓存图片的CHCHE,以便重绘时加快速度。如果说,每次都使用recycle的话,就达不到这个目的了。而且根据以往的经验,对于一般应用,根本就没有这个必要,内存过大,势必还有原因造成。
在“update heap”-“cause gc”,点击1-byte array(byte[], boolean[])行后,在Heap表里,查看图片内存的占用比例直方图,发现一些图片的占用内存居然高达10M(特别是在三星galaxy note运行时),但项目里最大的原始图片也才1M多,很明显程序的写法有问题。最后,发现,在资源文件里,设置android:background为某些图片时,导致内存大增。但如果把设置背景的步骤写在JAVA代码里,问题便解决了。
JAVA代码:
testview.setBackgroundResource(R.drawable.testview_bg);//内存还是会增大两三倍
结合上面的另一种作法,改用setBackgroundDrawable,如:
Bitmap bitmap = null;
            try
{
                bitmap
= BitmapFactory.decodeResource(context.getResources(),
                        res,
bfOptions);
            }
catch (OutOfMemoryError oom) {
                android.util.Log.e("getSDCardImageBitmapByUrl",
                        "OutOfMemoryError");
                System.gc();
                System.runFinalization();
            }
finally {

            }
            if
(bitmap != null && !bitmap.isRecycled()) {
                BitmapDrawable
bd = new BitmapDrawable(context.getResources(),
                        bitmap);
                v.setBackgroundDrawable(bd);
                //
bitmapCache.put(key, new WeakReference<Bitmap>(bitmap));
                drawableCache.put(key,
new WeakReference<Drawable>(bd));
            }
内存问题解决。
但是,setBackgroundResource和setBackgroundDrawable的差别为什么这么大,待研究。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: