Android – 从低内存条件恢复

我正在开发一个非常强烈的图像处理应用程序,我在水平FragmentStatePagerAdapter中有多个ListFragments.我积极地采用几乎每一个窍门和建议,我能够在这里和其他地方找到.我下载位图并将其保存到SD和软参考存储器缓存.

然而,当我在某些时候使用该应用程序,我开始在LogCat中看到消息,就像下面一样

11-05 15:57:43.951: I/dalvikvm-heap(5449): Clamp target GC heap from 32.655MB to 32.000MB
11-05 15:57:43.951: D/dalvikvm(5449): GC_FOR_MALLOC freed 0K,24% free 11512K/14983K,external 17446K/17896K,paused 64ms
11-05 15:57:44.041: D/dalvikvm(5449): GC_EXTERNAL_ALLOC freed <1K,24% free 11511K/14983K,external 17258K/17896K,paused 77ms

如果我继续,上面的消息将变得更加迫切

11-05 16:02:09.590: D/dalvikvm(5449): GC_FOR_MALLOC freed 0K,23% free 11872K/15239K,external 17497K/17896K,paused 71ms
11-05 16:02:09.700: D/dalvikvm(5449): GC_EXTERNAL_ALLOC freed <1K,paused 84ms
11-05 16:02:09.720: E/dalvikvm-heap(5449): 192816-byte external allocation too large for this process.
11-05 16:02:09.800: I/dalvikvm-heap(5449): Clamp target GC heap from 33.057MB to 32.000MB
11-05 16:02:09.800: D/dalvikvm(5449): GC_FOR_MALLOC freed 0K,paused 68ms
11-05 16:02:09.800: E/GraphicsJNI(5449): VM won't let us allocate 192816 bytes

并且不可避免的应用程序将与OutOfMemoryException崩溃
症状是经典的内存泄漏.在我的Fragment#onDestroy方法中,我取消所有待处理的任务,取消绑定和取消视图,并调用Bitmap#recycle.
有趣的是,我在LogCat中看到GC调用,但是即使我暂停长时间,内存也不会被回收.

我的直觉是,从SD中连续重新读取图像,导致退化和不可避免的死亡

这里的实用程序清理方法我正在试图摆脱drawables(有更多的我说要取消挂起/运行任务和空ListView适配器)

public static void unbindDrawables(View view,final boolean agressive) {
        if (view instanceof ViewGroup) {
            for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
                unbindDrawables(((ViewGroup) view).getChildAt(i),agressive);
            }
            if (!AdapterView.class.isinstance(view)) {
                ((ViewGroup) view).removeAllViews();
            }
        } else {
            Drawable bmp = view.getBackground();
            if (bmp == null && ImageView.class.isinstance(view)) bmp = ((ImageView) view).getDrawable();
            if (bmp != null) {
                bmp.setCallback(null);
                if (agressive && (TaggedDrawable.class.isinstance(bmp))) {
                    Bitmap bm = ((BitmapDrawable) bmp).getBitmap();
                    if (bm != null) {
                        if (DEBUG) Log.i(TAG,"Forcing bitmap recycle for " + bmp);
                        bm.recycle();
                        bm = null;
                        view.destroyDrawingCache();
                        view = null;
                    }
                }
            }
        }
    }

不用说,我在这一点上受到严重的打扰,非常感谢任何建议

解决方法

首先,GC一次不会回收内存.
这里有一些Android开发者网站的建议:

>不要保留长时间引用的上下文活动(引用
活动应该与活动的生命周期相同
本身)
>尝试使用上下文应用程序而不是上下文活动
>如果您不能控制,请避免活动中的非静态内部类
他们的生命周期,使用一个静态的内部类,并作出弱参考
到里面的活动这个问题的解决方案是使用a
静态内部类与外部类的WeakReference完全相同
在ViewRoot和它的W内部类中
垃圾收集器不是内存泄漏的保险

其次,当您不太在意位图的质量时,尝试使用BitmapFactory.options.

三,使用try catch来处理catch块中的OutOfMemory异常.

最后,使用Memory Analyzer.在Eclipse中打开DDMS,在工具栏中有一个更新堆按钮.您可以使用它来生成hprof文件,然后在andorid-sdk-tools目录中使用hprof-conv工具将文件转换为Memory Analyzer可以读取的指定格式文件.现在可以使用内存分析器来分析可能的内存泄漏.这真的是一个很好的工具,它会给你很多建议,以避免outofmemory.

希望这将帮助你,如果你找到一些更好的方法请告诉我,我也面对我的应用程序的outofmemory.

相关文章

这篇“android轻量级无侵入式管理数据库自动升级组件怎么实现...
今天小编给大家分享一下Android实现自定义圆形进度条的常用方...
这篇文章主要讲解了“Android如何解决字符对齐问题”,文中的...
这篇文章主要介绍“Android岛屿数量算法怎么使用”的相关知识...
本篇内容主要讲解“Android如何开发MQTT协议的模型及通信”,...
本文小编为大家详细介绍“Android数据压缩的方法是什么”,内...