まめージェント

Android, GAE, AngularJSの技術ネタ中心。Twitter: @mame01112

DialogFragmentでIllegalStateException "Fragment already added"が発生する

AndroidのFragmentを使っているとアルアルな話かもしれませんが、
FragmentDialogをつかっていて、二度目以降のタイミングで、

IllegalStateException "Fragment already added"

が発生する、という不具合に困っていました。
ようやくそれを修正できたので、その対応方法をシェア。

僕がやろうとしていたのは、ProgressFragment上のタイトルと本文を、
呼び出すActivity側から自由に設定して使い回す、というものでした。

しばらくやっていて/調べていて気づいたのは、

Bundle arguments = new Bundle();
arguments.putString("title", title);
arguments.putString("message", message);
instance.setArguments(arguments);

をやらなければ発生しない、ということ。
(つまり、DialogFragmentに渡されたTitleやMessageを
メンバ変数として保持しておく)

どうやら、1つのDialogFragmentに、2回以上setArgumentsすると、
IllegalStateExceptionを投げてくるようなのです。

できた!!
と思ったのもつかの間。
これだと、別のActivityから呼び出して表示したときに、
1つ目のActivityで設定したタイトルや本文が表示されてしまいました。

それはそのハズで、FragmentはAndroidのActivityのライフサイクルに
ベッタリなハズなので、勝手な、「なんちゃってSettter」なんてやっても、
うまく動くハズはありません。
(縦横回転とかでもおかしくなりそう・・・未確認)

じゃあ、どうするか。

対応策は、Android Developerに書いてありました。

DialogFragment | Android Developers
のサンプルコードのにありました。
FragmentManagerを使いましょうね、という話のようです。

この中で、FragmentManagerにDialogの生成から破棄まで任せてあります。
※DialogFragmentの使い方、というサンプルは世の中にたくさんあるんですが、
 なぜかFragmentManagerを使っての表示/非表示のコードがなかったので、
 全然気づかず・・・。

このやり方でやれば、IllegalStateExceptionも出ることがなくなりました。
よかったよかった。

僕はDialogFragmentの表示/非表示部分をまとめてラッパーのようなクラスを作り、
それをそれぞれのActivityから呼び出すようにしました。

教訓は、Android Developerはちゃんと読みましょうね、ということですね。