ImageView にセットした Bitmap はどうなるのか(2)

前回は、ImageView のソースコードを軽く解析して終わった。今回は実際に、エミュレーターを利用して ImageView に Bitmap をセットしてみる。利用したのは、Android 2.3(API 8)だ。
今回は、最初に Activity が終了する際に ImageView に貼り付けた Bitmap に recycle() メソッド呼び出しを行わないとどうなるのか調べてみた。DialogFragment に ImageView を用意して、大きな画像を読み込んで表示・非表示を繰り返したが、OutOfMemoryError は発生しなかった。特に手当てする必要なさそうな・・・

次に、ImageView に画像を何回も貼り付けてみることにした。ImageView の中の画像だけ変更するというのは、実際にありそうなコードだ。テストなので、単純にループで回すことにした。

for (int i = 0; i < 1000; i++) {
    Drawable d = detailPicture.getDrawable();
    Bitmap b = null;
    if (null != d) {
        BitmapDrawable bd = (BitmapDrawable) d;
        b = bd.getBitmap();
    }

    Bitmap bitmap = .../* ファイルから読み込む */
    imageView.setImageBitmap(bitmap);
}

このコードを実行しても、OutOfMemoryError は発生しない。いつもはよく会うお友達なのだが・・・BitmapDrawable から取得した b という Bitmap で isRecycled() を呼び出すと、imageView に setImageBitmap する前も後も false だった。また、頻繁に GC が発生する。大きなファイルを読み込む、1~2回に一度 GC が、小さなファイルを読み込むと 5~6回に一度 GC が発生した。

最初に戻って、Bitmap.recycled() メソッドの説明を読むと、最後の方に小さく(いや、小さいというのは嘘ですが)、

This is an advanced call, and normally need not be called, since the normal GC process will free up this memory when there are no more references to this bitmap.

Bitmap への参照がなくなれば、自然にメモリーは解放されますよということのようだ。今回の現象と一致しているので、参照が外されたタイミングを調べてみた。

ImageView は、setImageBitmap すると、BitmapDrawable を生成してセットしている。以前に Drawable がセットされていたときに、何を行うのか調べてみた。以下の順にメソッドが呼ばれていく(必要と思われる箇所のみ)。

ImageView.setImageBitmap(Bitmap)
ImageView.setImageDrawable(Drawable)
ImageView.updateDrawable(Drawable)
View.unscheduleDrawable(Drawable)
Choreographer.removeCallbacks(int, Runnable, Object)

removeCallbacks() メソッド内で、以前にセットされた Drawable は null になり、参照が外れた状態になっているのだろう。

じゃぁ、いつ recycle() するの?というのは次回までに調べておこうと思います。


1 thoughts on “ImageView にセットした Bitmap はどうなるのか(2)

  1. ピンバック: いざ、クオーターパウンダー ハバネロトマト! | UB Lab.

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

Time limit is exhausted. Please reload CAPTCHA.