Android 安卓:清理应用程序上的内存

Android 安卓:清理应用程序上的内存,android,memory-management,memory-leaks,out-of-memory,Android,Memory Management,Memory Leaks,Out Of Memory,我正在开发一个应用程序,它可以实例化一组位图对象(例如按钮,它有缓存位图,所以它们不必一次又一次地渲染) 现在,我意识到,当我在我的华为移动设备上反复运行和启动应用程序时,我会在应用程序试图为位图分配一些内存时出现OutOfMemoryException。 所以我猜是位图制造了麻烦。不过我知道有一个bitmap.recycle()方法 现在我的问题是:清理内存的最佳实践是什么? 为什么没有像View::onDestroy()这样的视图方法可以实现清理 编辑:示例 我的“CirclyButton”

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

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

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

编辑:示例

我的“CirclyButton”(extends Button)类始终在Draw上绘制缓存位图:

    @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;
    }

所以我想这些分配的数据应该在某个地方回收…?

视图没有
onDestroy
方法,因为视图通常不会被破坏,而活动会被破坏。如果视图的活动没有发生任何变化,视图不会被破坏(除非您使用不同的布局…情况并非如此,对吗?),如果视图的活动发生了变化,您会调用回调

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

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

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

提供了有关您在何处使用位图的更多信息,我在处理图像和节省内存方面有一些很好的经验

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


后来我决定优化我的列表,所以我将scroll listener添加到我的列表中,并开始在位图从屏幕上滚动下来时循环使用它们。

但是必须有一些方便的方法来做到这一点。想想可能有多少个按钮……所以将它们存储在一个数组中并迭代。这些是在布局中创建的还是通过代码创建的?如果您将它们存储在列表/数组中或跟踪它们的状态,这会使事情变得更容易。最重要的是,永远不要保留静态引用,除非您确定要处理它们。保持对
上下文的静态引用可能导致有史以来最严重的内存泄漏。什么是静态引用?你能给我举个例子吗?静态引用是类中的任何静态字段。静态字段是用单词
static
声明的字段。好的,现在告诉我在片段或活动的某些布局中,您在哪里使用这个按钮?现在我能给你的最好建议是,当保存这些图像的活动或片段正在执行时,回收这些图像。在您的视图组中定义一些方法,例如recycle(),它将回收所有资源……或者如果您是一名优秀的开发人员,请更改您的视图组,这样它将回收当前未显示的按钮的图像。然后在需要的时候从SD卡上获取这些图像,这不应该是一个长期的操作。