[Android] ListViewのlayoutをwrap_contentで指定しない

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

今回、ふとしたことで気づいたので備忘録としてまとめます。

ListViewのlayoutをwrap_contentで指定するとどうなるか。

まずは、簡単なコードでListViewのlayoutをwrap_contentで指定してみます。

layoutファイル activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

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

</RelativeLayout>

続いて、文字列のリストをListViewにセットします。

MainActivity.java

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        List<String> objectList = new ArrayList<String>();

        for (int i = 0; i < 10; i++) {
            objectList.add("title" + i);
        }

        ArrayAdapter<String> adapter = new ArrayAdapter<String>(getApplicationContext(),
                android.R.layout.simple_list_item_1, android.R.id.text1, objectList);

        ListView listView = (ListView) findViewById(R.id.ListView);
        listView.setAdapter(adapter);

    }
}

これで実行すると以下のような文字列のリストが表示できました。

listview_sample

しっかり表示されているので、OKですね。めでたしめでたし。。。。


と、思っていた時期もありました。(さっきまで)

MainActivity内のArrayAdapterを少し改良してログを見てみます。

MainActivity.java

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        List<String> objectList = new ArrayList<String>();

        for (int i = 0; i < 10; i++) {
            objectList.add("title" + i);
        }

        CustomAdapter adapter = new CustomAdapter(getApplicationContext(),
                android.R.layout.simple_list_item_1, android.R.id.text1, objectList);

        ListView listView = (ListView) findViewById(R.id.ListView);
        listView.setAdapter(adapter);

    }

    class CustomAdapter extends ArrayAdapter<String> {

        public CustomAdapter(Context context, int resource, int textViewResourceId,
                List<String> objects) {
            super(context, resource, textViewResourceId, objects);
        }
        
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            
            Log.d("getView","position:" + position);
            
            return super.getView(position, convertView, parent);
        }
        

    }
}

上記のように修正して、実行してみます。すると以下のようなログが出力されました。

LOGsample

なんか知らない間にgetViewめっちゃ呼ばれてるやん!  と、なります。

続いて、ListViewのlayoutをmatch_parentにしてみると...

activity_main.xml


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

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

</RelativeLayout>

これで実行し、ログを確認してみます。

logsample2

ちゃんと1回ずつ呼ばれてるやん! と、なります。

wrap_contentでは仮想的に何度も描画することがあるらしいので、その辺の関係でしょうか。

特に見た目などには変化はないですが、無駄とわかれば避けたほうがいいと思うので、極力match_parentで構築したいですね。

以上です