Android の「シングルトップ」起動モードと onNewIntent メソッド
-
19-09-2019 - |
質問
Androidのドキュメントを読んだところ、アクティビティのlaunchModeプロパティをsingleTopに設定するか、 FLAG_ACTIVITY_SINGLE_TOP
私の意図への旗、その呼びかけ startActivity(intent)
単一のアクティビティインスタンスを再利用し、 onNewIntent
折り返し電話。私はこれら両方のことを行いました、そして onNewIntent
決して発火しないし、 onCreate
毎回発火します。ドキュメントには次のようにも書かれています this.getIntent()
アクティビティが最初に作成されたときに最初に渡されたインテントを返します。で onCreate
電話してるよ getIntent
そして、毎回新しいものを取得しています(別のアクティビティでインテントオブジェクトを作成し、それにエクストラを追加しています...同じインテントオブジェクトを返していた場合、このエクストラは毎回同じであるはずです)。これらすべてのことから、私の活動は「シングルトップ」のように機能していないと私は信じていますが、その理由がわかりません。
必要な手順が単に欠けている場合に備えて背景を追加するために、マニフェスト内のアクティビティ宣言と、アクティビティの起動に使用しているコードを次に示します。アクティビティ自体は、これに関して言及する価値のあることは何も行いません。
AndroidManifest.xml 内:
<activity
android:name=".ArtistActivity"
android:label="Artist"
android:launchMode="singleTop">
</activity>
私の呼び出しアクティビティで:
Intent i = new Intent();
i.putExtra(EXTRA_KEY_ARTIST, id);
i.setClass(this, ArtistActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(i);
解決
onDestroy()
も同様に呼ばれたかどうかをチェックしましたか? onCreate()
は活動が既に存在した場合にのみ呼び出されます代わりにonNewIntent()
のたびに、呼び出された理由は、おそらくです。
たとえば、デフォルトで破壊されます。しかし、あなたが他の活動への活動の積み重ねの上に高く上がると、そこからもう一度ArtistActivity.class
を呼び出す場合の活動が既に作成されているためとonCreate()
Androidは作成されませんよう、あなたがそれを定義したので、それは、onNewIntent()
をスキップしてsingleTop
に直接移動します新しいITのインスタンスが、すでに周りに嘘をついているものを取ります。
私は私に何が起こっているのか確認するためにやっていることはので、私はいつも今何が起こっている各活動のすべての異なる状態のためのダミー関数を実装します
@Override
public void onDestroy() {
Log.i(TAG, "onDestroy()");
super.onDestroy();
}
同じonRestart()
、onStart()
、onResume()
、onPause()
、onDestroy()
のための
(BACKボタン)上記は、これらのダミーは、少なくともあなたが少し良くそれをデバッグするのに役立ちます実装、あなたの問題ではなかった場合。
他のヒント
受け入れられた答えは完全に正しくありません。onDestroy() が以前に呼び出された場合は、はい、onCreate() が常に呼び出されます。しかし、 この発言は間違っています:「アクティビティ スタックの上位に移動して他のアクティビティに移動し、そこから ArtistActivity.class を再度呼び出すと、onCreate() がスキップされ、直接 onNewIntent() に進みます。」
の「singleTop」セクション http://developer.android.com/guide/components/tasks-and-back-stack.html それがどのように機能するかをわかりやすく説明しています (以下の太字に注意してください。私自身のデバッグでもこれを証明しました)。
たとえば、タスクのバックスタックがルート アクティビティ A とその最上位にアクティビティ B、C、D で構成されているとします (スタックは A-B-C-D です。Dが上です)。インテントはタイプ D のアクティビティに到着します。D がデフォルトの「標準」起動モードを持つ場合、クラスの新しいインスタンスが起動され、スタックは A-B-C-D-D になります。ただし、D の起動モードが「singleTop」の場合、D の既存のインスタンスはスタックの最上位にあるため、onNewIntent() を通じてインテントを受け取ります (スタックは A-B-C-D のままです)。しかし、 タイプ B のアクティビティのインテントが到着すると、起動モードが「singleTop」であっても、B の新しいインスタンスがスタックに追加されます。
つまり、SINGLE_TOP を介してアクティビティを開始すると、既存のアクティビティが再利用されるのは、既存のアクティビティが再利用される場合のみです。 すでにスタックの一番上にあります. 。同じタスク内の別のアクティビティが先頭にある場合 (たとえば、startActivity(SINGLE_TOP) を実行しているアクティビティ) は機能しません。代わりに新しいインスタンスが作成されます。
これを修正する2つの方法があります これにより、必要な SINGLE_TOP 動作が得られます。その一般的な目的は、新しいアクティビティを作成するのではなく、既存のアクティビティを再利用することです。
最初の方法 (受け入れられた回答のコメントセクションで説明されているように):「singleTask」の launchMode をアクティビティに追加できます。これは、onNewIntent() を強制します。これは、singleTask は、特定のタスク内に特定のアクティビティのインスタンスが 1 つしか存在できないことを意味するためです。ただし、これはいくぶんハック的な解決策です。アプリが特定の状況でそのアクティビティの複数のインスタンスを必要とする場合 (私のプロジェクトでそうしているように)、あなたは台無しになります。
2 番目の方法 (より良い方法):FLAG_ACTIVITY_SINGLE_TOP の代わりに、FLAG_ACTIVITY_REORDER_TO_FRONT を使用します。これにより、既存のアクティビティ インスタンスがスタックの最上位に移動され、再利用されます (onNewIntent() が期待どおりに呼び出されます)。
FLAG_ACTIVITY_SINGLE_TOP の主な目的は、アクティビティの複数のインスタンスが作成されないようにすることです。たとえば、アプリケーションのメイン タスクの外部からのインテントを介してそのアクティビティを起動できる場合です。アプリ内のアクティビティ間の内部切り替えには、通常、代わりに FLAG_ACTIVITY_REORDER_TO_FRONT が必要であることがわかりました。
自分の意思にこのフラグを設定します:
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP)