2011-11-24 36 views
4

当我有两个简单的活动AB。通过按下按钮,用户从A开始B,然后用户通过按下后退按钮返回到A循环的竞争位图 - “试图使用回收的位图”重新推出活动

onDestroy()活动方法B中,我回收了活动B中使用的一些背景图像。我试图理解的是为什么当活动B再次启动时,我正在'尝试使用循环位图'。当然,位图会在onCreate()方法中再次加载?就像他们第一次开展活动一样。

这里是我的示例代码:

public class ActivityB extends Activity { 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);  
     setContentView(R.layout.selectionpage);  
    } 

    @Override 
    public void onDestroy() {  
     ImageView iv = (ImageView) findViewById(R.id.imageView1); 
     ((BitmapDrawable)iv.getDrawable()).getBitmap().recycle(); 
     LinearLayout ll = (LinearLayout) findViewById(R.id.linearLayout1); 
     ((BitmapDrawable)ll.getBackground()).getBitmap().recycle(); 
     super.onDestroy(); 
    } 
} 

我用从发射活动B代码A

 Intent intent = new Intent(ActivityA.this, ActivityB.class); 
    startActivity(intent); 

selectionpage.XML:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
     android:id="@+id/linearLayout1" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:background="@drawable/backgroundimage"> 

     <ImageView 
      android:id="@+id/imageView1" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:src="@drawable/selectionimage"/> 
     </LinearLayout>     

这部分可能是相关的。我不确定。我注意到,在启动活动B之后,即使它已被销毁,我仍然可以在使用MAT分析内存堆时看到我的活动实例。 GC根的路径似乎要经过Java.lang.Thread和ContextImpl。

回答

1

您得到该错误,因为ImageView iv & LinearLayout ll仍然指向回收的位图。您不需要在onDestroy()内自行回收。当系统不需要位图时,位图将被释放。

+1

是啊。我是一个白痴 - 我没有意识到这就是xml文件的工作原理。尽管我注意到的一件事是,在我的程序的另一个区域,我似乎在加载多个大图像后出现内存不足错误。即使一些图像不再被使用,GC似乎也不想删除它们。我不得不打电话给recycle() - 我相信要通知GC立即清理它们,而不是等一会儿。无论如何,我在散散步。感谢您的回答 – Wozza

+1

对于所有版本的android,这并非如此:'在Android 2.3.3(API级别10)及更低版本中,位图的后备像素数据存储在本机内存中。它与存储在Dalvik堆中的位图本身是分开的。原生内存中的像素数据不会以可预测的方式释放,可能会导致应用程序短暂超出内存限制并导致崩溃[http://developer.android.com/training/displaying-bitmaps/manage-memory]。html#inBitmap – ForceMagic

1

,如果你有一个单独的线程被保留活性比它应该更长的时间来活动的引用您可能有内存泄漏。

这可能会导致iv和ll旧活动在回收后仍然使用位图。你可以做iv.setImageDrawable(null)和ll.setBackgroundDrawable(null),但是这些位图是由系统创建的,你不需要回收它们。

我猜你试图回收它们,因为你遇到了内存问题?这可以通过上面提到的泄漏来更好地解释。

+0

我确实有内存问题,你是对的。我搜索了高和低,并找不到任何可能导致此活动有内存泄漏的引用。我试图回收,因为我不明白为什么当我开始活动B时,我失去了3Mb的堆空间。当我结束这项活动时,我似乎无法恢复。当我重新启动活动时,堆只增加几kbs。正如我所说,我已经看过内存转储,可以看到活动似乎仍然存在,但无论我停止/开始活动多少次,它仍然只有1副本 – Wozza

+0

你在做什么B - 你有吗?任何线程或异步任务?你有任何内部课程吗?你是否设置了类似drawable的视图或者查看静态变量?你是否保留了活动的实例? – FunkTheMonk

+0

我相信我在B中的问题是使用AdMob(我有一个横幅广告)。我尝试删除AdMob,并且所有内容似乎都很清晰。我认为adMob正在考虑我的背景,而不是摧毁自己,从而阻止其他任何事情被清理。 – Wozza

-1

你必须在代码中做到这一点。 不要启动位图对象中的代码并使用Imageview.setImageBitmap(位图)

Bitmap bitmap; 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.selectionpage); 
    bitmap = new BitmapFactory.decode... 
    yourImageView.setImageBitmap(bitmap); 

} 
@Override 
public void onDestroy() {  

    super.onDestroy(); 
    // do recycle bitmap here 
    bitmap.recycle(); 
} 
+0

此代码有很高的机会提升:致命异常:java.lang.RuntimeException:Canvas:尝试使用回收的位图[email protected]这意味着回收调用太早,而画布仍在使用它。 – ForceMagic