49

我在 Android 文档中读到,通过将我的 Activity 的 launchMode 属性设置为 singleTop 或通过将FLAG_ACTIVITY_SINGLE_TOP标志添加到我的 Intent,该调用startActivity(intent)将重用单个 Activity 实例并在onNewIntent回调中给我 Intent。我做了这两件事,onNewIntent从来没有onCreate每次都开火。文档还说,它this.getIntent()返回第一次创建时第一次传递给 Activity 的意图。在onCreate我打电话getIntent时,我每次都会得到一个新的(我在另一个活动中创建意图对象并添加一个额外的对象......如果它返回相同的内容,那么这个额外的对象每次都应该是相同的意图对象)。所有这一切让我相信我的活动不像“单顶”,我不

为了添加一些背景信息,以防我只是错过了一个必需的步骤,这是我在清单中的 Activity 声明和我用来启动 Activity 的代码。Activity 本身在这方面没有做任何值得一提的事情:

在 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);
4

3 回答 3

38

您是否也检查onDestroy()过是否被调用?这可能就是为什么onCreate()每次都调用而不是调用的原因onNewIntent(),只有在活动已经存在时才会调用它。

例如,如果您通过 BACK 按钮离开您的活动,则默认情况下它会被销毁。但是,如果您在活动堆栈中上升到其他活动并从那里ArtistActivity.class再次调用您的活动,它将跳过onCreate()并直接转到onNewIntent(),因为活动已经创建并且由于您将其定义为singleTopAndroid 不会创建它的新实例,但拿那个已经躺在身边的。

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

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

onRestart(), onStart(), onResume(), onPause(),也一样 onDestroy()

如果上面的(后退按钮)不是您的问题,那么实现这些假人至少可以帮助您更好地调试它。

于 2009-11-11T14:12:45.710 回答
34

接受的答案并不完全正确。如果之前调用了 onDestroy(),那么是的,总是会调用 onCreate()。但是,此语句是错误的:“如果您在活动堆栈中向上进入其他活动并从那里再次调用您的 ArtistActivity.class,它将跳过 onCreate() 并直接转到 onNewIntent()”

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

“例如,假设一个任务的后台堆栈由根活动 A 和顶部的活动 B、C 和 D 组成(堆栈是 ABCD;D 在顶部)。针对类型 D 的活动的意图到达。如果 D 具有默认“标准”启动模式,启动一个新的类实例,堆栈变为ABCDD。但是,如果D的启动模式是“singleTop”,则D的现有实例通过onNewIntent()接收intent,因为它在顶部堆栈的-堆栈仍然是 ABCD。但是,如果针对 B 类型的活动的意图到达,则将 B 的新实例添加到堆栈中,即使它的启动模式是“singleTop”。

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

这是解决此问题的两种方法,以便您获得所需的 SINGLE_TOP 行为——其一般目的是重用现有活动,而不是创建新活动......

第一种方式(如已接受答案的评论部分所述):您可以将“singleTask”的launchMode添加到您的活动中。这将强制 onNewIntent() 因为 singleTask 意味着在给定任务中只能有一个特定活动的实例。这是一个有点老套的解决方案,因为如果您的应用程序在特定情况下需要该活动的多个实例(就像我为我的项目所做的那样),那么您就完蛋了。

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

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

于 2015-09-18T23:33:11.747 回答
3

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

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP)
于 2016-08-25T01:20:52.510 回答