【问题标题】:android: cleaning up memory on app destroyandroid:清理应用程序销毁时的内存
【发布时间】:2012-01-15 15:09:43
【问题描述】:

我正在开发一个应用程序,它会实例化一堆位图对象(例如按钮,它们具有缓存位图,因此它们不必一次又一次地渲染)

现在,我意识到,当我在华为移动设备上反复运行和启动应用程序时,在应用程序尝试为位图分配一些内存时,我得到了 OutOfMemoryException。 所以我想是位图造成了麻烦。我确实知道有一个 bitmap.recycle() 方法。

现在我的问题是:清理内存的最佳做法是什么? 为什么没有像 View::onDestroy() 这样的 View 方法可以实现清理的目的?

编辑:示例

我的“CirclyButton”(扩展按钮)类总是在 onDraw 上绘制一个缓存的位图:

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawBitmap(this.getDefaultBitmap(), 0, 0, paint);
    }
    private Bitmap getDefaultBitmap(){
        if(mBitmapDefault == null){
            mBitmapDefault = Bitmap.createBitmap(8*radius, 8*radius, Config.ARGB_8888);
            Canvas canvas = new Canvas(mBitmapDefault);
            this.drawDefault(canvas);
            return mBitmapDefault;
        }
        return mBitmapDefault;
    }

所以我猜这个分配的数据应该在某个地方回收......?

【问题讨论】:

    标签: android memory-management memory-leaks out-of-memory


    【解决方案1】:

    视图没有onDestroy 方法,因为视图通常不会被销毁,活动会。如果它的活动没有发生任何事情,视图将不会被销毁(除非你膨胀不同的布局......不是这种情况,对吗?),如果它的活动发生了什么事,你确实有一个回调被调用。

    如果有 recycle() 方法,请确保调用它。并删除onDestroy中对内存占用对象的all引用,即:

    @Override
    public void onDestroy() {
        object1 = null;
        object2 = null;
        //...
    }
    

    所以 GC 可以完成它的工作。我对 AdMob 的 AdView 也有同样的问题,尽管他们确实有一个 destroy 方法,但它并没有真正帮助。但是删除我对视图的引用解决了这个问题。

    【讨论】:

    • 但是必须有一些方便的方法来做到这一点。想想可能有多少个按钮......
    • 所以将它们存储在一个数组中并迭代它们。这些是在布局中创建的还是通过代码创建的?
    • 好吧,如果您将它们存储在列表/数组中或跟踪它们的状态,这会使事情变得更容易。最重要的是,永远不要保留静态引用,除非你确定确定你将它们处理掉。保持对Context 的静态引用可能会导致最严重的内存泄漏。
    • 什么是静态引用?可以举个例子吗?
    • 静态引用是类中的任何静态字段。静态字段是用单词static 声明的字段。
    【解决方案2】:

    提供有关您在哪里使用位图的更多信息,我在处理图像和节省内存方面有一些认真的经验。

    例如,在我的应用程序中,我有一个数据列表,每行显示一些位图。我将我的列表存储在一个片段中(为了支持片段,我使用了兼容性库),并且我在这个片段的 onDestroy 方法上回收了我的位图。

    后来我决定优化我的列表,所以我在列表中添加了滚动监听器并开始回收位图,当它们被滚动出屏幕时。

    【讨论】:

    • 好的,现在告诉我你在哪里使用这个按钮,在片段或活动的某些布局中?我现在可以建议你的最好的事情是在保存它的活动或片段正在进行销毁时回收这些图像
    • 在你的视图组中定义一些类似 recycle() 的方法,它将回收所有资源......或者如果你让自己成为一个强大的开发人员,改变你的视图组,这样它就会回收未显示的按钮图像此时此刻。等下次需要的时候再从 SD 卡中获取这些图片,应该不是长期操作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-06
    • 2010-11-01
    • 2017-09-07
    • 1970-01-01
    相关资源
    最近更新 更多