...
class FooActivity extends Activity {
public static Hoge hoge_ = null;
...
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
hoge_ = new Hoge();
}
@Override
protected void onDestroy() {
hoge_.close();
super.onDestroy();
}
...
}
みたいな事をやってるんです。フッ、static な global 変数ですか?って笑われるかもしれませんが、正直、あちこちの Activity が関連を持って利用しなければならないとなると、こうするより他無いんです。こんなんで共有できてしまうのは、将来的に地雷を踏む可能性もあります。だって、アプリケーション全体でデータを共有するためには、どうしたらいいですか?に対する回答は、「ApplicationBean を使いましょう」だからです。データは、Parcelable で受け渡しすべきです。さて、この android.app.Application ですが、onDestroy に相当するメソッドがありません。正直言って使えません。また、画面の回転でレイアウトが変わる度に onDestroy と onCreate が呼ばれるので、うざくてしょうがありません。だから、私はダミーの BaseActivity を作成して、そこで共通リソースの初期化と破棄を行なってます。そうすれば、MainActivity の onDestroy と onCreate が何回呼ばれようが気にしなくて済みます。
話を巻き戻して、SingleTask なのに一時的に2重起動してもプロセスが別なら問題ないんじゃないですか?と思うやないですか?ところが、違うんです。この2つのアプリケーションから hoge_ が共有できてしまっており、先に終了したアプリの onDestroy よりも先に、後から起動したアプリの onCreate がコールされる状況があるんです。いや、もうビックリですね?しょうがないので、
...
class FooActivity extends Activity {
public static Hoge hoge_ = null;
private static int process_count_ = 0;
...
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if( 0 == process_count_ ) {
++process_count_;
hoge_ = new Hoge();
} else {
++process_count_;
}
}
@Override
protected void onDestroy() {
--process_count_;
if( 0 == process_count_ ) {
hoge_.close();
}
super.onDestroy();
}
...
}
という感じで、プロセス?カウントをとって、対処してます。ちなみにタイミングがシビアじゃ無いので、カウントの保護は一切行なっていません。
追記:static 変数の記述場所を間違えてたので修正しました。やっぱりカウンタは同期保護した方が良いかもしれません。synchronized(this)ではダメっぽい気がしますが、突っ込んでません。やるとすれば private static Object sync_ = new Object(); しておいて、synchronized(sync_) でしょうか?訂正: final 修飾子が余計だったのを取った。 2012/01/15 追記: どうも、Activity 再開時の挙動など、singleTask 等で細かく異なるようである。参考になるサイトを見つけた。こちらも目を通した方が良いです。一旦 HOME ボタンを押した後に再開すると、singleTask では BaseActivity の onDestroy がコールされるので思わしくない。
