質問: NavUtils.getParentActivityIntent(this); startActivity(intent) return true; } return super.onOptionsItemSelected(item); } ``` navigateUpFromSameTask の挙動は「親のアクティビティに遷移する」だと思っていたのですが、そうでないケースがあるようです。 そこで質問なのですが、親のアクティビティに遷移したい場合、 * 上記の startAcitivity を利用した方法で問題がないか * なぜ navigateUpFromSameTask が期待通りに動かないか を知りたいです。
回答: タスクの概念に関する理解が必要なように思います。 ざっくり説明すると、タスクというのは`Activity`のヒストリースタック、このケースで言えば、「A -> B -> C」のことをタスクと呼称します。詳細な説明は公式ドキュメントのTasks and Back Stackを参照ください。 ### Q.上記の startAcitivity を利用した方法で問題がないか 両者の挙動は全く異なるので、アプリケーションとしてどういう挙動を望むかによります。 `AndroidManifest.xml`に`Activity`の`launchMode`をどう指定したかによりますが、ほとんどの場合はデフォルトの`standard`かと思います。この場合、 ``` A -> B -> C ``` の状態から、Bを`startAcitivity()`した場合、 ``` A -> B -> C -> B ``` とスタックが積み重ねられます。一方、`navigateUpFromSameTask()`を利用した場合、 ``` A -> B ``` の状態になります。(`CLEAR_TOP`フラグが付与されて、Bが呼び出されます。また、Cの`Activity`を`finish()`する点も異なります) ### Q.なぜ navigateUpFromSameTask が期待通りに動かないか これについては`navigateUpFromSameTask`のドキュメント)に回答があります。 > > Note: This method should only be used when sourceActivity and the corresponding parent are within the same task. If up navigation should cross tasks in some cases, see shouldUpRecreateTask(Activity, Intent). > > > このメソッドは親となる`Activity`と呼び出し元`Activity`が同一のタスクに存在するときのみ利用すべきと記載されています。つまりAPIの利用目的から外れているのです。 では、このときの挙動はどうなっているのでしょう? 実装はJBかそれ未満かで変わります。JB以降の場合、`Activity#navigateUpTo()`)を呼び出しているだけなので、そちらのドキュメントより、 > > If the indicated activity does not appear in the history stack, this will finish each activity in this task until the root activity of the task is reached, resulting in an "in-app home" behavior. > > > 親`Activity`がヒストリースタックに存在しない場合、タスクのルートまで遡るとあります。このため、 ``` A ``` の状態になるのです。(JB未満では挙動が異なり、恐らく期待通りBが起動すると思います) ### 本来の利用想定ケース 例えば以下のような、 ``` A -> B -> C A -> B -> D -> C A -> B -> E -> C A -> B -> D -> E -> C ``` BからCへの遷移が複数パターンある場合、どのような遷移パターンであっても、`navigateUpFromSameTask()`を使うことで、 ``` A -> B ``` の状態になります。C自身と、中途の`Activity`がクリアされているのがポイントです。複雑な階層構造を持っていても、確実に親のポイントまで戻せるのが`navigateUpFromSameTask()`の便利な点なのですが、単純な親子構造を実現したい場合には存外不便です。