2014年5月29日木曜日

レイアウトファイルから作成するFragmentではsetArgumentsは使えない

レイアウトファイルから生成したFragmentに対してsetArgumentsを行ったところ ”Fragment already active” というエラーが起きた。

調べてみたところレイアウトファイルから生成されたFragmentではメンバのBundleがnullになるためsetArguments内で例外を投げられてしまうらしい。

Fragmentはレイアウトファイルから静的に生成されるケースとFragmentManagerより動的に生成・追加されるケースがあるが、それらの使い分けについて詳しく知る必要があると感じた。

参考URL:http://y-anz-m.blogspot.jp/2012/04/android-fragment-fragmenttransaction.html

2014年5月27日火曜日

PlaceholderFragmentとは

AndroidでデフォルトでActivityを作ったときに自動的に定義されるクラスPlaceholderFragment、今まで一体こいつが何なのか理解できていなかったが何となくわかってきたのでそれをメモする。

おそらくActivityにFragmentを乗せる方法としては二通りある。
  1. Activityのレイアウトxmlに独自のFragment要素を追加する。
  2. Activityのクラス内でPlaceholderFragmentのonCreateViewハンドラ内のinflateで独自Fragmentのレイアウトファイルを指定する。
因みに前者の場合、class属性で指定したFragmentを継承したクラス内のonCreateViewで表示したいViewを作成またはレイアウトファイルよりinflateする必要がある。

また、基本的に何かのイベントが起きてFragmentの表示を変えたいときにはFragmentManagerよりIDや名前を指定して指定のViewを引っ張って来れるため必ずしも、ある独自Fragmentに対してそれに対応するクラスを作る必要はない。

つまり、Fragment内のViewはどのクラスからでも操作が可能であるためPlaceholderFragmentという代表者をおいて独自Fragmentのクラスの代わりの処理を行うことができる。

PlaceholderFragmentを使用した場合、直感的にどのFragmentと対応付いているのかわかりづらいため前者の方が好ましい気がする。

追記:
今改めて当時に自分が書いた文章を読むとさっぱり何が言いたいのかがわからない・・・。

思い出すと、当時はFragment = Activityのインナークラスという様に理解をしていた。
また、お作法として独自のFragmentを使いたい場合はレイアウトファイルで定義してPlaceholderFragment内のonCreateViewのinflater.inflate()でそのレイアウトファイルを指定するものだと理解していた。

しかし、実際のお作法はそうではなくて、Fragmentを使いたいActivityのonCreate()内でFragmentManagerを呼び出して表示したいFragmentをインスタンス化してadd&commitするというものだった。

通常、FragmentはActivityとは別のクラスファイルとして作成管理すべきである。
そして、PlaceholderFragmentは単なるデフォルトの空のFragmentであり、ひとまず何でもいいからadd&commitするためインナークラスとして定義しているだけにすぎない。

でも、初めてAndroidでActivityを作ったときにFragmentがインナークラスで定義されていたらそういうものだって思ってしまうよね・・・。