Android ImageView - 開発Tips

こんにちは。

Android AppのImageViewを使って開発していろいろTipsがあったので、備忘録を兼ねてブログを書きます。

参考にしたのはこちらです。
http://d.hatena.ne.jp/komamitsu/20101209/1291907044
http://mtnk.org/down/PDF/OutOfMemoryError.pdf
http://d.hatena.ne.jp/hyoromo/20101001/1285943744
http://www.hoge256.net/2009/08/432.html
http://319ring.net/blog/archives/1269
http://lablog.lanche.jp/archives/192
http://d.hatena.ne.jp/hdk_embedded/20100518/1274121081
http://groups.google.com/group/android-group-japan/browse_thread/thread/fa40fe4d250541f5
http://ameblo.jp/yolluca/entry-10725668557.html

それでは早速書いてみます。

  • 画像読み込み中のアニメーションは、layoutでProgressBarを定義する。

ProgressBarを定義したものをLinearLayoutでincludeしましょう。
画像取得が終わったら、LinearLayoutのVisibilityをView.GONEにしてしまいましょう。
インターネットで、ViewFlipperで制御するやり方がありますが、Visibilityの制御とコストは変わらないので、ViewFlipperのViewを使うのとLinearLayoutのViewを使うのとでは、さまざまなコストが悪い気がします。
なので、Visibilityを制御するやり方が個人的にはしっくりきています。

  • 外部サイトの画像を表示する場合は、AsyncTaskが必須。

AsyncTaskにはConcurrentHashMap>でURLをキーにTask管理を行いました。
BitmapにはハードキャッシュのLinkedHashMapとソフトキャッシュのConcurrentHashMap>を使いました。
もちろんキーはURLです。
ハードキャッシュは、画像サイズを考えて、保持Bitmapデータ件数を調整しました。
ソフトキャッシュは、LinkedHashMap#removeEldestEntryのタイミングでハードキャッシュからソフトキャッシュに移動させてます。
あと、ListViewで画像表示する場合は、ListView#getViewで取得するViewに対して、setTagでModelクラスを設定しました。
そのModelクラスにBitmapを保持させてます。
このModelのBitmapの管理は、TaskのonCancelledが呼ばれたら、ModelのBitmapに対して、nullチェック、recycledチェックを行い、Bitmap#recycleを実施しました。

  • 外部サイトの画像を取得する際のBitmapFactory#decodeStramにはBitmapFactory.OptionsのinPurgeable = trueを設定して呼び出すといい。

このあたりは、上記の対策を含め、さまざまな箇所で、Bitmapのメモリ開放を実施して、OutOfMemory対策をするのがいいと思いました。

ちなみに、外部サイトから取得した画像データの0以下のデータはFilterInputStream#skipでスキップし読み込んでいます。

  • ListViewでのImageViewの取得をAsyncTaskにした場合は、ArrayAdapter#notifyDataSetChangedの呼び出しが必要。

これを行わないと、データ更新が行われません。
他の箇所でもViewの表示制御や更新、削除があった場合は、ArrayAdapter#notifyDataSetChangedは明示的に呼び出すようにしたほうがいいと思いました。

  • 最後に。

TODOは近いうちにチャレンジする機会があればやりたいですね。

  1. 画像とTaskキャッシュ機能を抽象化させて、公開したい。