スポンサーリンク

2012年8月25日土曜日

Androidプログラミング ArrayAdapter について

Androidプログラミンをやっていて、気づいた点のメモ。

配列データを ListView に表示する場合、一般的には配列から ArrayAdapter (またはそのサブクラス)インスタンスを作って、それを ListView に設定します。
例えば次のような配列があったとします。
String[] arrayData = {"apple", "banana", "grape", "Lemon"};
ArrayAdapter にはコンストラクタがいくつもあって、例えば上の配列から ArrayAdapter インスタンスを作るにも何通りかの方法があります。

方法1
ArrayAdapter<String> adapter = 
    new ArrayAdapter<String>(this, R.layout.rawdata, arrayData);
この方法はコンストラクタで配列を与えています。別の方法として以下の様なやり方もあります。

方法2
ArrayAdapter<String> adapter = 
    new ArrayAdapter<String>(this, R.layout.rowdata);
for (String str : arrayData) {
    adapter.add(str);
}

この方法はコンストラクタでは入れ物だけを作って、後から add() メソッドで配列データを追加していきます。

最初はどちらの方法もまったく同じだと思っていました。どちらかというとコードがすっきりする方法1をよく使っていました。しかしこの二つは大きな違いがあったのです。

何が違うかというと、方法1で作った ArrayAdapter は、引き渡した配列データの要素は内部的には List<T> のかたちで保存されているのに対し、方法2の場合 ArrayList<T> のかたちで保存されているのです。(型パラメータTは今回の場合 String)

この違い分かりますか?大きな違いは ArrayList<T> は要素を削除・追加出来るのに対し、List<T> はできないということです。このことにより、ArrayAdapter の remove() や clear() メソッドを呼び出すと、方法1のアダプタでは例外(UnsupportedOperationException)が発生します。方法2のアダプタでは正しく削除されます。

結局、内容がダイナミックに変化する ListView には方法2 を使えということのようです。反対に固定的で変化しない ListView はどちらを使っても良いのですが、変化しないことの安全性を確保するのであれば、方法1 を使うのが良いでしょう。

これ、結構重要な違いだと思うのですが、Javadocには何も書かれていません。ソースコードを追いかけて気がつきました。Android の Javadoc にはこういう重要なことが平気で書かれていないので、注意が必要です。