Locked History Actions

Android/Views

AndroidのViewについて

AndroidのViewの概念は、一見他のGUIツールキットと同じように見えるのだが、大きく違うところがある。 様々な書籍やウェブサイトでの記事もこの点を明確に指摘しているところは、ほぼ存在しない。

つまり、Android特有の用語が何を意味するのか全く定義せずに話を進めているため、読む方としては 何のことやらわからないという状態になってしまう。 様々なGUIツールキットを経験している人間であるほど理解不能に陥ってしまう。

※以下は認識不足である可能性があります。注意してお読みください。

Swing等との違い

AndroidではSwing等のコンポーネントと同じように、Viewを入れ子にして画面を作成していく。 ViewはSwingの場合のコンポーネントに対応する。

しかし、ListViewなど、実行時までその中身の繰り返し数がわからない場合の扱いはSwingとAndroidでは全く異なる概念になる。

Swingでは、リストコンポーネント等に対してデータ(モデル)を与えれば、そのコンポーネント自体の大きさが変化して、すべてのデータが表示できるようにしてくれる。もし、このコンポーネントがScrollPaneの上にあれば、適切にスクロールバーがつけられる。

しかし、Androidではそうはいかないようだ。ListViewに任意の数のデータを表示するには、その同じ数のViewを用意して、それらをListViewに置いてやらないといけないらしい(実際にはそれほど面倒ではないし、必ずしもすべてを用意する必要もないのだが、概念的にはこういうことになる)。

Swingのコンポーネントのように、一つのコンポーネントの中で繰り返しデータをすべて表示するという発想ではなく、必要なだけViewを作成しなければならないのである。

※さらに細かいことを言えば、Swingの場合には、その中身(例えば、JTableのセル)の表示や編集においては、そのセルごとに異なるコンポーネントが作成できるようにはなっているが、実際には一つのコンポーネントが使いまわされるケースが多い。

Adapter

これを簡単に行ってくれるのがAdapterなのだが、この言葉はもちろんSwingのとは全く概念的に異なる。

Swingでは主にイベントリスナインターフェースの空の実装を差している場合が多い。 これに対してAndroidでは、「与えられたデータと同じ数の適当なViewを作成して、そこにデータを設定してListViewなどに載せてくれるもの」という意味である(再度、あくまでもこれは概念的な話)。

多くの書籍等の説明では、データとListViewなどをとりもつ役割などと簡単にしか説明していないので、Swing使いには「モデルの役割」であると誤解されてしまう可能性があるのだが、全くそうではない。

Inflater

さらに、Inflater, Inflate, Inflationという言葉は、これが何を差しているのか、どこを探しても全く説明が見つからない。 AndroidのリソースシステムとJavaコードの橋渡しをする重要な役割を担うものであるにも関わらず。

これは単純にリソース中のXMLに記述されたView定義をもとにJavaオブジェクトを作成するということらしい。

ただし、単純に一対一、つまり一つのXML定義からただ一つのJavaオブジェクトが作成されるのではなく、inflate操作を行うごとにいくつでもJavaオブジェクトを作成できるようだ。つまり、XML定義は単なるテンプレートである。

このため、例えば、先のAdapterのように「いくつのViewが必要であるかわからない」というケースでは、その数だけ該当するXML定義をInflateしてViewのJavaオブジェクトを作成してやるということになる。

※ただし、inflateは「重い」操作であるので、大量にViewオブジェクトを作成する場合は、inflateではなく直接Viewオブジェクトを作成してしまった方が良いようだ。

ショートカットによる誤解

例えば、ActivityのonCreate()のメソッド内でsetContentView(R.layout.main)などと、リソースIDを指定することを、単純に「コンテンツビューを指定する」などと説明してしまうと、これも大きな誤解のもとになる。

APIの説明は「Set the activity content from a layout resource. The resource will be inflated, adding all top-level views to the activity.」となっている。

つまり、リソースをコンテンツビューに指定するのではなく、指定されたリソースから作成された(inflateされた)Javaオブジェクトをコンテンツビューとして指定するのである。これは単純にショートカットに過ぎない。

そもそもリソースは後回しでよい

多くの書籍、多くのウェブサイトにて初めから「レイアウト」にまでリソースを使わせているが、これがそもそもおかしい。 リソースは必要になった時に使えばよいものであり、かつ必要であるかどうかはプログラムを記述している本人自身が認識すべきものである。 初めからリソースなど使う必要はないのである(もちろん、画像等はリソースにしておかなければアクセスできないようであるが)。

リソースを使うことによりコードが分断されると、それだけ理解しにくくなることは明らかである。 なおかつ、Androidのリソースには名前空間が無いので、巨大なプログラムを作成しようとすれば、この点は必ず問題になるはずなのであるが (あるいは、回避方法があるはずなのだが)、どういうわけかそのような指摘をしている書籍やウェブサイトも無いようだ。

さらに、レイアウトまでリソースにする最も大きな理由というのは、単にGUIビルダが使用できることである。 もちろん、Androidではデバイスの特性に合わせて自動的に異なるリソースを選択してくれるということもあるのだが、あまりメリットとは思えない。

リソースにしないことによるメリットはこれらをはるかに上回る。

  • 先に述べたように、コードが分断されないためわかりやすくメンテナンスしやすい。
  • リソースの単一名前空間ではなく、Javaのパッケージ名前空間が使用できる。
  • プログラムの制御によって、例えばすべてのボタンの色を一度に変更することができる。
  • 定型的な複合Viewを使いまわすことができる。リソースのXML定義では、重複して同じ作業を繰り返さなければならない。
  • リソースを一切含まないプロジェクトであるなら、それをjarの形のライブラリにしておくことができる。

最後の点は、Google推奨の(あるいは、多くの書籍やウェブサイトが盲目的に従っている)開発方法しか知らない者にとっては盲点である。

リソースを伴なうプロジェクトはjarファイルの形にして簡単に使いまわすということができないのである。Eclipse ADTを使用する場合は「プロジェクト参照」を行わなければならない。これは、モジュール化という観点から大きな問題かと思われる。