41

Androidドキュメントで、アクティビティのlaunchModeプロパティをsingleTopに設定するか、FLAG_ACTIVITY_SINGLE_TOPフラグをMy Intentに追加すると、その呼び出しでstartActivity(intent)が1つのActivityインスタンスを再利用してくれますonNewIntentコールバックのインテント。私はこれらの両方を行い、onNewIntentは決して発火しません。毎回onCreateが発火します。ドキュメントでは、this.getIntent()は、アクティビティが最初に作成されたときにアクティビティに最初に渡されたインテントを返します。 onCreateで私はgetIntentと呼んでいます。毎回新しいものを取得しています(私は別のアクティビティでインテントオブジェクトを作成しており、それに余分なものを追加しています...この余分なものは、同じインテントオブジェクト)。このすべてが、私の活動は「シングルトップ」のようには行動していないと信じています。私はその理由を理解していません。Android "single top"起動モードとonNewIntentメソッド

必要な手順が不足している場合のために背景を追加するには、マニフェストのアクティビティ宣言とアクティビティの開始に使用しているコードを次に示します。 onDestroy()が呼び出されたかどうかをチェックしました

 Intent i = new Intent(); 
     i.putExtra(EXTRA_KEY_ARTIST, id); 
     i.setClass(this, ArtistActivity.class); 
     i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); 
     startActivity(i); 
+2

は、このスライドショーを確認してください。 launchModeは非常に良いと説明しています。http://www.slideshare.net/RanNachmany/manipulating-android-tasks-and-back-stack – Malachiasz

答えて

36

:のAndroidManifest.xmlで

:私の呼び出し活動における

<activity 
     android:name=".ArtistActivity" 
     android:label="Artist" 
     android:launchMode="singleTop"> 
    </activity>  

活動自体は、このに関しては言及する価値が何もしません同じように?つまり、onNewIntent()の代わりにonCreate()が毎回呼び出されるのはおそらくそうです。これは、アクティビティが既に存在する場合にのみ呼び出されます。

例えば、あなたの活動を戻るボタンで放置すると、デフォルトで破壊されます。しかし、あなたがアクティビティスタックを他のアクティビティに上げてそこからあなたのArtistActivity.classを呼び出すと、onCreate()はスキップされ、onNewIntent()に直接移動します。アクティビティはすでに作成されているため、singleTopと定義されています。それの新しいインスタンスが、すでに横たわっているものを取る。私は私に何が起こっているのか確認するために何

ので、私はいつも今何が起こっている各活動のすべての異なる状態のためのダミー関数を実装:

onRestart()onStart()onResume()onPause()onDestroy()のための同じ
@Override 
public void onDestroy() { 
    Log.i(TAG, "onDestroy()"); 
    super.onDestroy(); 
} 

上記の(BACK-ボタン)が問題でなかった場合、これらのダミーを実装することは、少なくとも少しデバッグするのに役立ちます。

+0

これはおそらく起こっていることです。エントリーポイントとして「ランディングページ」のようなものを作成しました。着陸点からアーティストを選択し、ArtistActivityに移動します。ユーザーは、戻るボタンを使用してメインアクティビティに戻り、再度選択します。私は最初の使用の後にアクティビティがハングアップし、再インスタンス化しないことでパフォーマンスを節約できるという印象を受けました。ここでのパフォーマンスについて心配すべきか、単純なアクティビティではこのパターンはうまくいくのでしょうか? – Rich

+2

こんにちは、私はOPと同じ問題を抱えていますが、onDestroyは私の場合は決して呼び出されません。他のアイデア? – kellogs

+0

@kellogs、私と同じことが起こっています.. :-(何かまだですか? – ghostCoder

23

回答が正しいとは限りません。以前にonDestroy()が呼び出された場合は、onCreate()が常に呼び出されます。しかし、このステートメントは間違っています: "アクティビティスタックを他のアクティビティに上げて、そこからArtistActivityを呼び出すと、

http://developer.android.com/guide/components/tasks-and-back-stack.htmlの「singleTop」セクションでは、どのように動作するかを簡単に説明しています(下の太字のテキストに注意してください、私自身のデバッグでもこれを証明しています) :

"たとえば、タスクのバックスタックは、アクティビティB、C、およびDがアクティビティB、C、Dで構成されているとします(スタックはABCD、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の動作を得るための2つの方法です - 一般的な目的...代わりに新しいものを作成するのではなく、既存のアクティビティを再利用することである

まず道(受け入れ 解答のコメントセクションで説明したように):あなたがあなたの活動に「singleTask」のlaunchModeを追加することができます。これはonNewIntent()を強制します。なぜなら、singleTaskは、指定されたタスク内の特定のアクティビティのインスタンスが1つしかないことを意味するからです。これはややハックな解決策ですが、あなたのアプリが特定の状況でそのアクティビティの複数のインスタンスを必要とする場合(私のプロジェクトのように)、あなたは嫌です。

第二の方法(良い): 代わりのFLAG_ACTIVITY_SINGLE_TOP、FLAG_ACTIVITY_REORDER_TO_FRONTを使用しています。これは、既存のアクティビティインスタンスをスタックの一番上に移動して再利用します(onNewIntent()は期待通りに呼び出されます)。

FLAG_ACTIVITY_SINGLE_TOPの主な目的は、アクティビティの複数のインスタンスの作成を防止することです。たとえば、そのアクティビティを、アプリケーションのメインタスクの外部からのインテントによって起動することができます。私のアプリでのアクティビティ間の内部切り替えについては、FLAG_ACTIVITY_REORDER_TO_FRONTが一般的に私が代わりに必要なものであることがわかりました。あなたの目的には、このフラグを設定

+1

ありがとうございます。実際に受け入れられた解答の説明は、 "singleTask"ビヘイビアには適していますが、アップナビゲーションでは1つのアクティビティーの複数のインスタンスを作成できる "singleTop"ではありません。 – GuillermoMP

+1

2つ目の方法では、FLAG_ACTIVITY_REORDER_TO_FRONTの使用はlaunchModeの "singleTop"権利と組み合わせる必要がありますか? – yat0

+0

本当に良い答えです、これは受け入れられるものです。 –

3

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP) 
関連する問題