2011-08-12 21 views
18

据我了解(不是我是正确的)当应用程序完成时,Drawables通常会正确地从内存中删除。然而,位图需要手动回收,有时甚至会写一个特殊的类来处理它们。 我的问题是,在关于内存和泄漏,是它更为有利简单地绘项目棍子像这样:Drawable vs Single可重用Bitmap与内存更好?

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(); 

我已经当然也读过,您必须小心地使用Bitmap上的recycle()方法,因为它们可以在仍然使用的情况下被移除?似乎这些问题以不同形式出现,但我无法从这个问题上得到任何人的直接答复。一个人说,重复使用位图,每次使用后回收,和其他人说使用可绘制和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(); 
    } 
} 

任何适用的洞察力会非常赞赏,虽然。谢谢

回答

8

我回过罗曼的建议,但我不确定你的问题是解决你的实际问题。我不知道你如何处理对你的Views的引用。也许你只是在你的应用程序中有内存泄漏? Android中的大量内存泄漏与Context有关。当Drawable连接到View时,View被设置为Drawable上的回调。

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

在上面的代码段,这意味着Drawable有一个参照其本身具有的Activity(在Context)的引用TextView这反过来有引用这取决于你的代码几乎任何东西。

没有看更多的代码我猜你已经在正确的轨道上,当Activity被销毁时,将存储的绘图的回调设置为null

+0

谢谢,非常好的资料。我通过findViewById(R.Id.Image_name)获取我的视图;顺便说一句。不知道这是否以某种方式留下了对上下文的引用。 –

9

位图不需要需要手动回收。它们就像Drawables和其他物体一样被垃圾收集。同样,除非在特定情况下,您不需要解除绑定。看来你读了很多误导性的信息。 (如果您的应用程序处理大量位图数据的实例,或者您存储绘制以静态方式。)

回收位图和解除绑定绘制可以在某些情况下非常有用

这两个例子告诉你开头你的问题是相同的。如果直接加载drawable,位图将代表您加载。如果您手动加载位图并将它们设置在ImageView上,它们将代表您以可绘制形式包含在它们中。

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

+0

以及我问的原因是因为我确实需要内存管理技术。我点击一个按钮来操作多个视图的图像,这是我的菜单系统。除非我滚动浏览每个菜单,然后退出并再次完成,否则没关系。经过几次应用程序崩溃,因为“位图超过VM限制OOM”。不肯定它为什么这样做,但是当我使用unbindDrawables()方法时,它不会发生。或者至少我还没有能够重新创建它。 –

+3

你必须非常小心地预蜂窝关于位图。前蜂窝,位图分配在Java垃圾回收器无法访问的RAM空间中。这导致内存泄漏。如果你在Honeycomb之后,那么你是对的。 –

+1

位图在本机堆上分配的事实不会导致内存泄漏。它只是意味着您必须等待终结器才能在位图被释放之前运行。 –

相关问题