OnDestroyのビットマップをリサイクルする - アクティビティを再起動するときに「リサイクルされたビットマップを使用しようとしています」

私は A B という2つの簡単なアクティビティを持っています。ユーザーはボタンを押して A から B を開始し、戻るボタンを押して A に戻ります。

アクティビティ B onDestroy()メソッドでは、アクティビティ 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();
     }
 }

The code I use to launch activity B from A

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

selectionpage.XML:



        
                        

この部分は関連しているかもしれません。よく分かりません。私はアクティビティBを起動した後でも、MATを使用してメモリヒープを解析するときに、アクティビティBが破棄された後でも、自分のアクティビティのインスタンスを確認できます。 GCルーツへのパスは、Java.lang.ThreadとContextImplを経由しているようです。

4

3 答え

You get that error because ImageView iv & LinearLayout ll are still pointing to recycled bitmaps. You don't need to do recycling yourself inside onDestroy(). Bitmaps will be freed when they are not needed by the system.

1
追加された
これはアンドロイドのすべてのバージョンでは当てはまりません:Android 2.3.3(APIレベル10)以下では、ビットマップのバッキングピクセルデータがネイティブメモリに保存されます。 Dalvikヒープに格納されているビットマップ自体とは別のものです。ネイティブメモリ内のピクセルデータは予測可能な方法で解放されないため、アプリケーションが一時的にメモリ制限を超えてクラッシュする可能性があります。 developer.android.com/training/displaying-bitmaps/…
追加された 著者 ForceMagic,
うん。私はばかだ、私はそれがxmlファイルがどのように動作するのか分からなかった。私が気付いたことの一つは、私のプログラムの別の領域では、いくつかの大きな画像を読み込んだ後にメモリエラーが出ているようです。画像の一部がもう使用されなくなっても、GCはそれらを削除したくないようです。私はそれらにリサイクル()を呼び出さなければならない - 私はしばらく待つよりもすぐにそれらをきれいにするためにGCに通知すると信じている。とにかく、私は散歩している。ご回答有難うございます
追加された 著者 Wozza,

あなたが必要以上にアクティビティを保持している別のスレッドのアクティビティへの参照がある場合は、メモリリークが発生する可能性があります。

これにより、古いアクティビティのivとllが、リサイクルされた後もビットマップを使用し続ける可能性があります。 iv.setImageDrawable(null)とll.setBackgroundDrawable(null)を実行できますが、これらのビットマップはシステムによって作成されているため、リサイクルする必要はありません。

私は、あなたが記憶上の問題に遭遇したためにあなたがそれらをリサイクルしようとしていると推測していますか?上記の可能性のある漏れによってよりよく説明されるだろう。

1
追加された
あなたはBで何をしていますか?スレッドまたは非同期タスクがありますか?あなたは内部クラスを持っていますか? drawableやviewのようなものを静的変数に設定していますか?あなたは活動のインスタンスをまったく保持していますか?
追加された 著者 FunkTheMonk,
私はあなたが正しい記憶問題を抱えています。私は高低を検索しており、このアクティビティでメモリリークが発生する可能性のある参照を見つけることはできません。アクティビティBを開始したときに3Mbのヒープスペースを失う理由を理解できないため、リサイクルしようとしていました。私が活動を終えると、私はそれを取り戻すことはできません。アクティビティを再開すると、ヒープは数KB増加するだけです。私が言うように、私はメモリダンプを見て、アクティビティがまだ存在するように見えますが、何度もアクティビティを停止/開始してもまだ1つだけです
追加された 著者 Wozza,
Bの私の問題はAdMob(私はバナー広告を持っている)だと思います。 AdMobを削除しようとしましたが、すべてがうまくクリアされているようです。私はadMobが自分の文脈をとって、自分自身を破壊していないと思います。
追加された 著者 Wozza,

コードで実行する必要があります。 コード内でビットマップオブジェクトを開始し、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();
 }
1
追加された
このコードは、高いチャンスを上げています:致命的な例外:java.lang.RuntimeException:キャンバス:リサイクルされたビットマップ[email protected]を使用しようとしています。
追加された 著者 ForceMagic,