2

多くの画像を表示するカスタム ビュー (グリッド ビューに似ています) を作成したので、このアプリケーションではビットマップのリサイクルが必要です。ビットマップのリサイクルを処理するために、Lru キャッシュ (以下に実装) を使用しています。これを Android 2.3 デバイスでテストした (そして高速でスクロールした) と、次のエラー メッセージが表示され、アプリがクラッシュしました。バグを再現する方法を見つけた後、Android 4.0 でテストしたところ、問題なく動作しました。

06-27 10:57:48.420: E/AndroidRuntime(14255): FATAL EXCEPTION: main
06-27 10:57:48.420: E/AndroidRuntime(14255): java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@407fc6b8
06-27 10:57:48.420: E/AndroidRuntime(14255):    at android.graphics.Canvas.throwIfRecycled(Canvas.java:955)
06-27 10:57:48.420: E/AndroidRuntime(14255):    at android.graphics.Canvas.drawBitmap(Canvas.java:1044)
06-27 10:57:48.420: E/AndroidRuntime(14255):    at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:325)
06-27 10:57:48.420: E/AndroidRuntime(14255):    at android.widget.ImageView.onDraw(ImageView.java:872)
etc etc

このバグを追跡したところ、ビットマップを ImageView に設定する前に、ビットマップがリサイクルされているかどうかを確認することがわかりました。ただし、ビットマップはそのステップと draw() ステップの間でリサイクルされ、エラーが発生します。

ここに私のキャッシュがあります:

sLruCache = new LinkedHashMap(容量 / 2, 0.75f, true) {
      private static final long serialVersionUID = -7282875042976381535L;

      @オーバーライド
      protected boolean removeEldestEntry(LinkedHashMap.Entry eldest) {
        if (size() > mCapacity) {
          true を返します。
        } そうしないと
          false を返します。
      }

      public Bitmap remove(オブジェクトキー) {
        ビットマップ ビットマップ = super.remove(key);
        if (ビットマップ != NULL_BITMAP) {
          ビットマップ.リサイクル();
        }
        ビットマップを返します。
      };

      @オーバーライド
      public void clear() {
        キーを設定 = new HashSet(keySet());
        for (文字列キー: キー) {
          ビットマップ マップ = get(キー);
          if (マップ != NULL_BITMAP) {
            map.recycle();
          }
        }
        super.clear();
      }
    };

これが4.0ではなくAndroid 2.3で失敗する理由についてのアイデアはありますか?

4

1 に答える 1

0

私も同じ問題を抱えてる。

そして、すべての Bitmap.recycle() 呼び出しを削除する必要がありました。OutOfMemoryException が発生することがありました。

したがって、私は次のようなハックを行います。

// when I need to remove bitmap from cache
if (Build.VERSION.SDK_INT < 9 || Build.VERSION.SDK_INT > 10) {
    bmp.recycle();
}   

良い解決策ではありませんが、役立つ場合があります。

于 2013-08-14T08:44:50.017 に答える