まず最初に、API 17(Android 4.2)までのデバイスをターゲットにしている場合はtargetSdkVersion
、マニフェストでを17に設定します。これは古いデバイスのサポートを壊すことはなく、新しいデバイスで正しく機能するようにするだけです。もちろん、それはあなたの問題を解決しません-それをするのは良いことです。
何を使うべきですか?
このページのAncestralNavigationの例に基づいてコードを作成していると思います。2番目の例を使用しました。
Intent upIntent = new Intent(this, MyParentActivity.class);
if (NavUtils.shouldUpRecreateTask(this, upIntent)) {
// This activity is not part of the application's task, so create a new task
// with a synthesized back stack.
TaskStackBuilder.from(this)
.addNextIntent(new Intent(this, MyGreatGrandParentActivity.class))
.addNextIntent(new Intent(this, MyGrandParentActivity.class))
.addNextIntent(upIntent)
.startActivities();
finish();
} else {
// This activity is part of the application's task, so simply
// navigate up to the hierarchical parent activity.
NavUtils.navigateUpTo(this, upIntent);
}
ただし、必要な動作については、次のように置き換える必要がありますNavUtils.navigateUpTo
。
upIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(upIntent);
finish();
なぜICS以前で動作するのですか?
一般に、サポートライブラリは、後のAPIで導入された動作を概算しようとしています。の場合NavUtils
、サポートライブラリはAPI 16(別名Android 4.1)で導入された動作を概算しようとしています。API 16より前のプラットフォームの場合、NavUtilsは以下を使用します。
@Override
public void navigateUpTo(Activity activity, Intent upIntent) {
upIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
activity.startActivity(upIntent);
activity.finish();
}
これは、で指定されたアクティビティのインスタンスのバックスタックを調べますupInent
。見つかった場合は、それまでのすべてをクリアして復元します。それ以外の場合は、アクティビティを起動するだけです。
API 16以降のプラットフォームでは、サポートライブラリがActivity
APIのネイティブ呼び出しに処理を渡します。ドキュメントによると:
パブリックブールnavigateUpTo(Intent upIntent)
このアクティビティからupIntentで指定されたアクティビティに移動し、プロセスでこのアクティビティを終了します。upIntentで示されたアクティビティがタスクの履歴にすでに存在する場合、このアクティビティと、履歴スタックで示されたアクティビティの前にある他のすべてのアクティビティが終了します。
示されたアクティビティが履歴スタックに表示されない場合、タスクのルートアクティビティに到達するまで、このタスクの各アクティビティが終了し、「アプリ内ホーム」動作が発生します。これは、正規の親アクティビティを通過しないパスがアクティビティに到達する可能性がある場合に、複雑なナビゲーション階層を持つアプリで役立ちます。
upIntent
そのことから、バックスタックにない場合にで指定されたアクティビティを起動するかどうかは不明です。ソースコードを読んでも、物事を明確にするのに役立ちません。ただし、アプリが示している動作から判断すると、アクティビティを起動しようとはしていないようです。upIntent
どちらの実装が正しいか間違っているかに関係なく、最終的にはFLAG_ACTIVITY_CLEAR_TOP
、ネイティブAPI 16の動作ではなく、動作が必要になります。残念ながら、これはサポートライブラリの概算を複製する必要があることを意味します。
どちらが正しい?
免責事項:私はGoogleで働いていないので、これが私の最善の推測です。
私の推測では、API16以降の動作は意図された動作です。これは、Androidの内部にアクセスでき、APIでは不可能なことを実行できる組み込みの実装です。API 16より前では、インテントフラグを使用する以外に、この方法でバックスタックを巻き戻すことはできなかったと思います。したがって、FLAG_ACTIVITY_CLEAR_TOP
フラグは、 API16より前のプラットフォームで使用可能なAPI16の動作に最も近いものです。
残念ながら、その結果、ネイティブ実装とサポートライブラリ実装の間に、シナリオで驚き最小の原則に違反することになります。それは、これがAPIの予期しない使用であるかどうか疑問に思います。つまり、Androidは、アクティビティに直接ジャンプするのではなく、アクティビティへの完全なナビゲーションパスをトラバースすることを期待しているのだろうか。
念のため
考えられる誤解を1つ回避するためshouldUpRecreateTask
に、親がバックスタックにないことを魔法のように判断し、を使用してすべてを合成するプロセスを実行することを誰かが期待する可能性がありますTaskStackBuilder
。
ただし、shouldUpRecreateTask
基本的に、アクティビティがアプリによって直接起動されたか(この場合は戻りますfalse
)、別のアプリから起動されたか(この場合は戻りますtrue
)を決定します。この本から、サポートライブラリはインテントの「アクション」がそうでないかどうかをチェックしますACTION_MAIN
(私はそれを完全には理解していません)が、API16プラットフォームではタスクアフィニティに基づいてこのチェックを実行します。それでも、このアプリの場合、shouldUpRecreateTask
falseを返すようになります。