2014年7月7日月曜日

Android : ListView と GridView の違い - 画面サイズに応じて ListView と GridView を切り替えるパターンで GridView の場合にパフォーマンスが低下する

ListView と GridView の違いは、GridView なら複数列使用できる、というくらいだと思っていたのですが、そうではなかったというお話です。GridView の方が getView の呼び出しがかかる事が多いです。

参考 : Multiple calling of getView() in GridView

AndroidStudio では、New -> Fragment -> Fragment (List) というメニューがあり、これを選択して、「Switch to grid view on large screens?」というオプションにチェックを入れておくと、画面サイズに応じて ListView と GridView を切り替えてくれる Fragment と xml ファイルが追加されます。
(Use Layout Aliases というドキュメントにある手法を使っています。)

これは便利、と思っていたのですが、Nexus7 (GridView) でデバッグしていると Nexus5 (ListView) でデバッグしているときと比較して明らかにパフォーマンスが落ちることに気がつきました。調べていくと、謎のタイミングで getView() が呼ばれていることがわかりました。

  • 最初のレイアウトの時点で、子の View の数以上の getView が呼ばれている
  • 子の View をクリックした際に呼ばれている
    • notifyDatasetChanged() 等は使っておらず、ListView の時は getView が起こらないことを確認済み
  • GridView の高さが変わった時に呼ばれている
    • 広告が表示されたタイミングで GridView の高さ(Padding の大きさ)を再設定するようにしていたのですが、ここでも、GridView の場合のみ getView が呼ばれていました。

グリッドを正しく複数行に表示するための処理と思われますが、なかなか厄介です。
参考先では、先頭の View で getView が  33回呼ばれていた、というような絶望的な報告もありました。View をキャッシュしておくことで対応したそうです。getView の中身が相当軽い場合はそのままでよいかもしれませんが、GridView を使う場合は view の内容をキャッシュする、というテクニックは覚えておいた方がよさそうです。(メモリは使うでしょうが、単純に getView の中身が重い場合の ListView にも使えそうです。)

0 件のコメント:

コメントを投稿