2

Android 用のキャッシュ イメージ システムを作成しようとしていますが、メモリ消費量がどんどん増えていきます。いくつかのアイデアを求めて AndroidのWeb サイトを調べましたが、問題が消えたくないだけです。

以下は、SDカードから画像を取得し、設定して後で破棄する私のコードです。私は何を間違っていますか?

WeakReference<Bitmap> newImageRef;
    public void setImageFromFile(File source){
        if(source.exists()){

            Bitmap newImage = BitmapFactory.decodeFile(source.getAbsolutePath());
            newImageRef =   new WeakReference<Bitmap>(newImage);
            if(newImage != null){
                this.setImageBitmap(newImage);
            }
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        Bitmap newImage = newImageRef.get();
        if (newImage != null) {
        newImage.recycle();
        newImage = null;
        }


        Drawable drawable = getDrawable();
        if (drawable instanceof BitmapDrawable) {
            BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
            Bitmap bitmap = bitmapDrawable.getBitmap();
            if (bitmap != null){
            bitmap.recycle();
            }
        }
        this.setImageResource(0);
        newImage = null;
        newImageRef = null;
        System.gc();


        super.onDetachedFromWindow();
    }
4

3 に答える 3

2

Android バージョン >3.0 を使用している場合はrecycle()、gc への参照がない限り、gc が最終的にビットマップを自動的にクリーンアップするため、呼び出す必要はありません。したがって、リサイクル呼び出しを削除しても安全です。彼らはここでは何もしません。

あなたが投稿したコードはきれいに見えますが、リークがどこかで起こっていないことを確信していますか. Android Memory Analyzer ツールを使用して、リークが発生している場所を確認し、情報を投稿してください。

幸運を。

于 2013-06-26T15:35:33.283 に答える
1

使ってみてくださいDrawable.setCallback(null);recycleAndroid 3.0 以降では、以前のバージョンよりもメモリ管理やガベージ コレクションが自動化されているため、その必要さえありません。これも参照してください。Android でのビットマップ メモリ管理に関する優れた情報が含まれています。

于 2013-06-26T17:27:39.180 に答える
0

このコードの時点では、詳細なバグがあるかどうかを確認するのは困難です。これは明らかに「フル キャッシュ」の単純化されたバージョンであるように思われるからです。少なくとも、あなたが提供した数行は問題ないようです。

主な問題は、ビットマップを処理するときに GC が少し奇妙に見えることです。ハード参照を削除しただけでは、ビットマップ オブジェクトの割り当て方法が原因で、ビットマップがしばらくの間ハングすることがあります。前に述べたように、Android 3 以降ではリサイクルは必要ありません。そのため、大量のビットマップを追加する場合、このメモリが再び解放されるまでに時間がかかる場合があります。または、メモリ リークがコードの別の部分にある可能性があります。このような高度な問題については、再実装する前に、すでに証明されたソリューションを確認するのが賢明です。

これは 2 番目の問題につながります: 弱い参照の使用です。これは主な問題を対象としていない可能性がありますが、 android docによって記述されているように、Android 2.3+ の画像キャッシュに使用するのは一般的に適切なパターンではありません。

注: 以前は、一般的なメモリ キャッシュの実装は SoftReference または WeakReference ビットマップ キャッシュでしたが、これはお勧めできません。Android 2.3 (API レベル 9) 以降、ガベージ コレクターはより積極的にソフト/ウィーク参照を収集するようになり、かなり効果がなくなりました。さらに、Android 3.0 (API レベル 11) より前のバージョンでは、ビットマップのバッキング データはネイティブ メモリに格納されていましたが、予測可能な方法で解放されなかったため、アプリケーションが一時的にメモリ制限を超えてクラッシュする可能性がありました。

ここで行う方法は、LRU キャッシュを使用することです。これについては、キャッシングについて提供されているリンクで詳しく説明されています。

于 2013-06-26T20:59:25.747 に答える