Android"单顶"启动模式和onNewIntent方法

Ric*_*ich 43 java android android-manifest android-intent android-activity

我在Android文档中读到,通过将我的Activity的launchMode属性设置为singleTop或者通过向FLAG_ACTIVITY_SINGLE_TOP我的Intent 添加标志,该调用startActivity(intent)将重用单个Activity实例并在onNewIntent回调中给我Intent .我做了这两件事,每次都onNewIntent不会发射和onCreate射击.文档还说,它this.getIntent()返回首次创建时首次传递给Activity的意图.在onCreate我打电话getIntent,每一次(我创建另一个动作的意图对象,并增加一个额外的给它我得到一个新的...这额外的应该是相同的,每次如果它回到我同样的意图对象).所有这些让我相信我的活动并不像"单一顶级",我不明白为什么.

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

在AndroidManifest.xml中:

    <activity
        android:name=".ArtistActivity"
        android:label="Artist"
        android:launchMode="singleTop">
    </activity>     
Run Code Online (Sandbox Code Playgroud)

在我的通话活动中:

        Intent i = new Intent();
        i.putExtra(EXTRA_KEY_ARTIST, id);
        i.setClass(this, ArtistActivity.class);
        i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        startActivity(i);
Run Code Online (Sandbox Code Playgroud)

znq*_*znq 36

你有没有检查是否onDestroy()也被调用了?这可能是为什么onCreate()每次调用而不是调用onNewIntent(),只有在活动已经存在时才会调用.

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

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

@Override
public void onDestroy() {
    Log.i(TAG, "onDestroy()");
    super.onDestroy();
}
Run Code Online (Sandbox Code Playgroud)

同为 onRestart(),onStart(),onResume(),onPause(),onDestroy()

如果上面的(BACK按钮)不是你的问题,实现这些假人至少会帮助你更好地调试它.

  • android:launchMode ="singleTask" - 在我看来,有问题的ACtivity是从它的主要任务之外开始的 (16认同)
  • 嗨,我和OP有同样的问题,但onDestroy在我的情况下永远不会被调用 - 我最终得到了活动的全新实例:-s.还有其他想法吗? (2认同)
  • @kellogs很棒的小费.我正在使用基于NFC的应用程序,每次用标签触摸手机时,我的活动的新实例就开始了.Jump-Back-Hierarchy是一团糟.launchmode ="singleTask"帮助很多,运行时enironment阻止多次实例化相同的活动,这对我帮助很大!谢谢. (2认同)

Ste*_*e B 29

接受的答案并不完全正确.如果先前调用了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()接收意图,因为它位于顶部堆栈的堆栈 - 堆栈仍然是ABCD.但是,如果一个意图到达类型B的活动,那么即使其启动模式为"singleTop",也会向堆栈添加一个新的B实例.

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

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

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

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

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

  • 谢谢你。事实上,公认的答案解释适用于“singleTask”行为,但不适用于“singleTop”,其中向上导航可以创建一个活动的多个实例。 (2认同)