2

我在互联网上阅读了很多关于屏幕旋转位图和内存泄漏的帖子和评论。

实际上,我遇到的问题非常特殊......

我使用 Eclipse DDMS,我正在查看 1 字节数组占用的堆内存,这与我放置在四个 ImageView 中的位图有关,每个位图都位于 ViewFlipper 的页面中。这些图像是从内部存储器加载的,大小为 216-220KB,我使用了一个可绘制的图层,以便在它们之上绘制另一个透明图像。

注意位图占用的堆内存,如果我改变设备的方向,内存会增加一些 MB。导致 2-3 GC,在几分钟内内存量减少到初始值。慢慢重复这个过程(改变方向+ 2-3 强制垃圾收集),内存量增加,但随后又回到相同的值。这让我觉得我在我的应用程序中使用位图管理做得很好。

但是如果我开始反复快速旋转设备,我会看到内存量不断增加....与快速旋转期间的快速增长相比,后续 GC 只能减少少量内存的堆占用.

Android不能这么快收集垃圾吗?为什么如果我缓慢旋转,我能够保持内存使用稳定,而不是如果我反复快速旋转而不强制 GC 一段时间?

安卓 4.1.2 / 三星 Galaxy S3。

每当从内部存储读取 png 或由 AsyncTask 从 Internet 下载时,都会调用以下代码。禁用 AsyncTasks(因此通过后续旋转排除挂起的任务)不会改变场景,在启动时从内部存储加载两个“层”就足以在旋转设备时快速填充堆。

public void setBitmap(Bitmap bitmap) 
{
    try{
        Drawable layers[] = new Drawable[2];
        Bitmap fvgBackgroundBmp = BitmapFactory.decodeResource(getResources(), R.drawable.fvg_background2);
        layers[0] = new BitmapDrawable(getResources(), fvgBackgroundBmp);
        layers[1] = new BitmapDrawable(getResources(), bitmap);
        LayerDrawable layerDrawable = new LayerDrawable(layers);
        setImageDrawable(layerDrawable);
        mLayerDrawableAvailable = true;
    }
    catch(Exception outOfMemory)
    {
        Log.e("setBitmap got exception", outOfMemory.getLocalizedMessage());
    }
}

从'sunbindDrawables()调用的方法没有帮助:ActivityonDestroy()

public void unbindDrawables()
{
    if(mLayerDrawableAvailable)
    {
        LayerDrawable lDrawable = (LayerDrawable) getDrawable();
        if(lDrawable != null)
        {   
            lDrawable.getDrawable(1).setCallback(null);
            lDrawable.getDrawable(0).setCallback(null);
            lDrawable.setCallback(null);
        }
    }
}
4

2 回答 2

0

当内存压力很高时,不保证调用 onDestroy。这或许可以解释。尝试从 onStop() 调用 unbindDrawables

http://developer.android.com/training/basics/activity-lifecycle/stopping.html#Stop

于 2013-05-17T01:29:18.673 回答
0

我会尝试从您的可绘制图层中取回位图并回收它。

public void unbindDrawables()
{
    if(mLayerDrawableAvailable)
    {
        LayerDrawable lDrawable = (LayerDrawable) getDrawable();
        if(lDrawable != null)
        {   
            ((BitmapDrawable)lDrawable.getDrawable(1)).getBitmap().recycle();
            ((BitmapDrawable)lDrawable.getDrawable(0)).getBitmap().recycle();
            lDrawable.setCallback(null);
        }
    }
}

尝试在您的活动中调用 onDestroy() 事件主体中的 unbindDrawables()。

于 2013-10-15T13:24:04.733 回答