trying to use a recycled bitmap androidを完璧に解決する.graphics.Bitmap@41dの異常


最近のプロジェクトでは、AnimationDrawableを使って動画を再生するため、画質が大きく、再生頻度が多く、開発されたドライブレコーダーのメモリが限られていて、最初はBitmap recycleを落とさなかったため、OOMの異常が発生しました.メモリオーバーフローの問題を解決するために、現在のページを終了するときにBitmap recycleを削除します.しかし、ここでもう一つの問題が発生し、現在のインタフェースを終了してこのページに入るとtrying to use a recycled bitmap androidが報告される.graphics.Bitmap@41dの異常です.
その後、多くの文章を読んだが、本当にこの問題を解決することはできず、ソースコードから調べるしかなかった.
解析問題が発生したのは、drawableをロードしたときにbitmap recycleが再使用される可能性があるため、この問題が発生したためです.ソースコードgetResource(context)を追跡します.getDrawable(id)==コード=>loadDrawable(value,id);ここではキーコードが見えます
 Drawable dr = getCachedDrawable(isColorDrawable ? mColorDrawableCache : mDrawableCache, key);

        if (dr != null) {
            return dr;
        }

ここで、キャッシュDrawableが空でなければ、元の使用していたDrawableに戻ります.ここでは、このDrawableが参照していたBitmapはrecycleされていますが、Drawableというキャッシュオブジェクトは、その失効したBitmapをずっと参照しています.このBitmapを再ロードしないようにシステムリソースを節約するためにシステムが設計されていることは理解できますが、ここでは大量の画像を使ってアニメーションを再生する(大きな画像をロードするだけでメモリオーバーフローを防ぐ必要があるため、ページを終了するときにrecycleという画像を再生する)ので、システムのこの方法は私たちにとって逆効果になります.
問題の要点を見つけたら、私たちはこの問題の解決に着手します.
1、ページを終了してonDestory()コールバックを実行するとき、画像リソースを回収し、AnimationDrawableのオブジェクトを空にし、GCを呼び出してシステムをできるだけ早く回収させる
@Override
	protected void onDestroy() {
		super.onDestroy();

		
		//             
		tryRecycleAnimationDrawable(animation);
		AnimationDrawble  
		animation = null;
		   AnimationDrawble     
		tv.setBackground(null);
		      
		System.gc();
	}
	// AnimationDrawable          
	private void tryRecycleAnimationDrawable(
			AnimationDrawable animationDrawables) {
		if (animationDrawables != null) {
			animationDrawables.stop();
			for (int i = 0; i < animationDrawables.getNumberOfFrames(); i++) {
				Drawable frame = animationDrawables.getFrame(i);
				if (frame instanceof BitmapDrawable) {
					Bitmap bitmap = ((BitmapDrawable) frame).getBitmap();
					bitmap.recycle();
					bitmap = null;
				}
				frame.setCallback(null);
			}

			animationDrawables.setCallback(null);

		}
	}

2、重点は再びプログラムに入ってからcacheDrawableを呼び出さないと残念なことに、私たちのデフォルトのシステムリソースをロードする方法getResource(context)です.getDrawable(id)はデフォルトでこのメソッドを呼び出してリソースをロードします.私たちは別の近道を開くしかありません.システムの最も原始的な方法を使ってピクチャーの資源BitmapFactoryをロードします.decodeResource(Resources, resId);
しかし、この方法は画像資源大会がここでOOMを作りやすい場合は、この部分の処理を一時的に省略し、この文章を読んだ子供靴は自分でどのように処理するか知っていると信じています.ここで最新のBitmapを入手した後、new AnimationDrawableでbitmapをロードすればOKです
人によって使用シーンが異なり、ビジネスも異なります.上記の問題が解決できない場合は、いくつかのブログを参考にしてください.
http://blog.csdn.net/u010829905/article/details/50233207   Android bitmap.recycle()によるtrying to use a recycled bitmapエラー分析
http://blog.csdn.net/yaya_soft/article/details/44064249Androidはbitmapを手動で回収し、Canvas:trying to use a recycled bitmap処理を開始
http://blog.csdn.net/sex_34/article/details/47725707   Canvas: trying to use a recycled bitmap android.graphics.Bitmap@XXX