20

据我了解(不是我是正确的)当应用程序完成时,Drawables 通常会正确地从内存中删除。然而,位图需要手动回收,有时甚至需要编写一个特殊的类来正确处理它们。我的问题是,关于内存和泄漏,像这样简单地坚持使用 Drawables 是否更有益:

myView.setBackgroundDrawable(getResources().getDrawable(R.drawable.my_image));
myView1.setBackgroundDrawable(getResources().getDrawable(R.drawable.my_image1));
myView2.setBackgroundDrawable(getResources().getDrawable(R.drawable.my_image2));

而不是像位图这样的东西:

Bitmap tmpBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.my_image);
myView.setImageBitmap(tmpBitmap);

tmpBitmap.recycle();
tmpBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.my_image1);
myView1.setImageBitmap(tmpBitmap);

tmpBitmap.recycle();
tmpBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.my_image2);
myView2.setImageBitmap(tmpBitmap);
tmpBitmap.recycle();

我当然也读过,您必须小心位图上的 recycle() 方法,因为它们可以在仍在使用时被删除?似乎这些问题不断以不同的形式出现,但我真的无法从任何人那里得到一个直接的答案。有人说每次使用后都要重用 Bitmap 并回收,还有人说使用 Drawables 和 unbindDrawables() 方法(这是我一直在使用的):

private void unbindDrawables(View view) {
    if (view.getBackground() != null) {
        view.getBackground().setCallback(null);
    }
    if (view instanceof ViewGroup) {
        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
            unbindDrawables(((ViewGroup) view).getChildAt(i));
        }
        ((ViewGroup) view).removeAllViews();
    }
}

不过,任何适用的见解将不胜感激。谢谢

4

2 回答 2

9

位图不需要手动回收。它们像 Drawable 和其他对象一样被垃圾收集。同样,您不需要取消绑定可绘制对象,除非在非常特殊的情况下。您似乎阅读了很多误导性信息。

在某些情况下,回收位图和取消绑定 drawable 可能很有用(例如,如果您的应用程序处理大量位图数据或您以静态方式存储 drawable。)

您在问题开头显示的两个示例是等效的。如果您直接加载可绘制对象,则将代表您加载位图。如果您手动加载位图并将它们设置在 ImageView 上,它们将代表您包含在可绘制对象中。

使用第一个解决方案,因为它更简单,并且在您真正需要它们之前不必担心解除绑定和其他内存管理技术。

于 2011-08-12T18:59:23.310 回答
8

我支持 Romain 的提议,但我不确定您的问题是否解决了您的实际问题。我不知道您如何处理对您的视图的引用。也许您的应用程序中只是存在内存泄漏?Android 中的很多内存泄漏都与Context. 当 aDrawable附加到 aView时,将View设置为 上的回调Drawable

TextView myView = new TextView(this);
myView.setBackgroundDrawable(getDrawable(R.drawable.my_bitmap));

在上面的代码片段中,这意味着 theDrawable有一个引用TextViewwhich 本身有一个对Activity(the Context) 的引用,而后者又引用了几乎任何东西,具体取决于您的代码。

在不查看更多代码的情况下,我猜您通过将存储的可绘制对象的回调设置为销毁null时处于正确的轨道上。Activity

于 2011-08-12T22:33:53.073 回答