ListViewを含むDialogFragmentの表示を速くする

目次

症状

custom view を表示するリストを DialogFragment で表示させようとしたところ、Dialog が表示されるまで二秒以上かかっていました。

どこで時間がかかるのか調べてみると、ListView に設定した adapter のgetView()メソッドが繰り返し呼び出されていました。

改善方法

そこで同じような例がないかとググってみると、layout_heightを match_parent にすればgetView()メソッドの無駄な呼び出しを抑えられるというページ(注1)を見つけました。

そこで DialogFragment 内で AlterDialog.Builder に設定する View を次のようにしてみましたが、最初の getView から最後まで 2.1 秒もかかって効果はありませんでした。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/node_list_view" />
</LinearLayout>


12-27 12:29:22.896 31433-31433/jp.nosuz.* D/DialogList: getView: 0
12-27 12:29:22.916 31433-31433/jp.nosuz.* D/DialogList: getView: 1
...
12-27 12:29:25.028 31433-31433/jp.nosuz.* D/DialogList: getView: 7
12-27 12:29:25.028 31433-31433/jp.nosuz.* D/DialogList: getView: 8

そこでさらに検索するとRelativeLayout が有効というページ(注2)を見つけました。

このページに従って LinearLayout を次のように Relative に書き換えると、getView()メソッドを呼び出す回数がぐっと減りました。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/node_list_view" />
</RelativeLayout>

最初の getView から最後まで 2.1 秒かかっていたものが 0.07 秒になり、表示されるまでの「あれ?」というストレスがなくなりました。

12-27 12:39:58.967 9244-9244/jp.nosuz.* D/DialogList: getView: 16
12-27 12:39:58.977 9244-9244/jp.nosuz.* D/DialogList: getView: 15
12-27 12:39:58.987 9244-9244/jp.nosuz.* D/DialogList: getView: 14
12-27 12:39:59.007 9244-9244/jp.nosuz.* D/DialogList: getView: 13
12-27 12:39:59.007 9244-9244/jp.nosuz.* D/DialogList: getView: 12
12-27 12:39:59.017 9244-9244/jp.nosuz.* D/DialogList: getView: 11
12-27 12:39:59.027 9244-9244/jp.nosuz.* D/DialogList: getView: 10
12-27 12:39:59.027 9244-9244/jp.nosuz.* D/DialogList: getView: 9
12-27 12:39:59.037 9244-9244/jp.nosuz.* D/DialogList: getView: 8

欠点

ただしlayout_heightに match_parent を指定しているので、表示する項目数が少ない場合にも Dialog が最大の大きさで表示され無駄な空白ができてしまいます。

参照

  1. custom listview adapter getView method being called multiple times, and in no coherent order – stackoverflow
  2. DialogFragment + listview = getView called too many times