安卓“单顶”启动模式及开启新方法

我在 Android 文档中读到,通过将活动的 launchMode 属性设置为 singleTop 或将标志添加到我的 Intent,该调用将重用单个 Activity 实例,并在回调中为我提供 Intent。我做了这两件事,从来没有每次都开火和开火。文档还说,返回首次创建活动时首次传递给活动的意图。在我正在打电话,我每次都会得到一个新的(我正在另一个活动中创建意图对象,并向其添加额外的对象......这个额外的每次都应该是相同的,如果它返回我相同的意图对象)。所有这些都使我相信我的活动并不像“单一顶部”,我不明白为什么。FLAG_ACTIVITY_SINGLE_TOPstartActivity(intent)onNewIntentonNewIntentonCreatethis.getIntent()onCreategetIntent

为了添加一些背景知识,以防我只是缺少必需的步骤,下面是清单中的 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);

答案 1

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

例如,如果您通过“后退”按钮离开活动,默认情况下它会被销毁。但是,如果您在活动堆栈上上升到其他活动的较高位置,然后从那里再次调用,它将跳过并直接转到 ,因为该活动已经创建,并且由于您将其定义为Android,因此不会创建它的新实例,而是采用已经存在的实例。ArtistActivity.classonCreate()onNewIntent()singleTop

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

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

与 、 、 、 相同onRestart()onStart()onResume()onPause()onDestroy()

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


答案 2

接受的答案并不完全正确。如果之前调用了 onDestroy(),那么是的,onCreate() 将始终被调用。但是,这种说法是错误的:“如果你在活动堆栈上上升到其他活动的位置,然后从那里调用你的ArtistActivity.class它将再次跳过onCreate()并直接转到onNewIntent()”

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

“例如,假设任务的后退堆栈由根活动 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 类型的活动到达了意向,则 B 的新实例将添加到堆栈中,即使其启动模式为“singleTop”。

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

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

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

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

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


推荐