Android“单顶”启动模式和onNewIntent方法

我在Android文档中看到,通过将Activity的launchMode属性设置为singleTop,或者通过将FLAG_ACTIVITY_SINGLE_TOP标志添加到我的Intent,调用startActivity(intent)将重用单个Activity实例,并在onNewIntentcallback中为我提供Intent。 我做了这两件事情,并且onNewIntent每次都不会触发和创build。 该文档还说, this.getIntent()返回首次创build时传递给Activity的意图。 在onCreate我调用getIntent ,我每次都得到一个新的(我在另一个活动中创build意图对象,并添加一个额外的东西…这额外应该是每次都是一样,如果它是返回我同一个意图对象)。 所有这一切使我相信,我的行为不是“单顶”,我不明白为什么。

要添加一些背景,以防万一我只是缺less一个必需的步骤,这里是我在清单中的活动声明和我用来启动活动的代码。 这个活动本身并没有做任何值得一提的事情:

在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() ,只有在活动已经存在时才会调用onNewIntent()

例如,如果您通过“后退”button离开活动,则默认情况下会被销毁。 但是,如果您将活动堆栈放在其他活动中, ArtistActivity.class再次调用ArtistActivity.class ,则会跳过onCreate()并直接转到onNewIntent() ,因为该活动已经创build,并且您singleTop其定义为singleTop Android不会创build它的一个新的实例,但采取已经躺在那里的一个。

我做什么来看看发生了什么事情我为每个活动的所有不同状态实施虚拟函数,所以我总是现在发生了什么事情:

 @Override public void onDestroy() { Log.i(TAG, "onDestroy()"); super.onDestroy(); } 

onRestart()onStart()onResume()onPause()onDestroy()

如果上面的(返回button)不是你的问题,那么实现这些假人至less可以帮助你更好地debugging它。

接受的答案是不完全正确的。 如果之前调用了onDestroy(),那么是的,onCreate()将始终被调用。 然而, 这个说法是错误的 :“如果你把活动堆栈放到其他活动中,再从那里调用你的ArtistActivity.class,它会跳过onCreate()直接到onNewIntent()

http://developer.android.com/guide/components/tasks-and-back-stack.html的“singleTop”部分清楚地解释了它是如何工作的(注意下面的粗体文本;;我也通过我自己的方式certificate了这一点debugging):

“例如,假设一个任务的返回堆栈由根活动A组成,活动B,C和D在顶部( 堆栈是ABCD; D在顶部 ),一个意图到达typesD的活动。如果D具有默认的“标准”启动模式,启动一个新的类实例,堆栈变为ABCDD,但是如果D的启动模式是“singleTop”,则D的现有实例通过onNewIntent()接收到意图,因为它在顶部堆栈保持ABCD,但是如果一个意图到达typesB的活动,那么即使它的启动模式是“singleTop”,堆栈的新实例也会被添加到堆栈中。

换句话说,通过SINGLE_TOP开始一个活动只会重用现有的活动,如果它已经在堆栈的顶部 。 如果同一任务中的另一个活动位于顶部(例如,正在执行startActivity(SINGLE_TOP))的活动,则不起作用; 将会创build一个新的实例。

以下是解决这个问题的两种方法,以便您获得所需的SINGLE_TOP行为 – 其一般用途是重用现有活动,而不是创build新活动。

第一种方式 (如接受的答案的注释部分所述):您可以将“singleTask”的launchMode添加到您的活动中。 这将强制onNewIntent(),因为singleTask意味着在给定任务中只能有一个特定活动的实例。 这是一个有点hacky解决scheme,虽然因为如果你的应用程序需要在特定情况下(如我为我的项目)的多个实例的活动,你搞砸了。

第二种方法(更好):使用FLAG_ACTIVITY_REORDER_TO_FRONT而不是FLAG_ACTIVITY_SINGLE_TOP。 这将通过将现有活动实例移动到堆栈的顶部来重用(onNewIntent()将按预期方式调用)。

FLAG_ACTIVITY_SINGLE_TOP的主要目的是防止创build一个Activity的多个实例。 例如,当这个活动可以通过来自应用程序的主要任务之外的意图来启动时。 对于我的应用程序中的活动之间的内部切换,我发现FLAG_ACTIVITY_REORDER_TO_FRONT通常是我想要的。

将此标志设置为您的意图:

 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP)