Java Android“单顶”启动模式和onNewIntent方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1711785/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android "single top" launch mode and onNewIntent method
提问by Rich
I read in the Android documentation that by setting my Activity's launchMode property to singleTop OR by adding the FLAG_ACTIVITY_SINGLE_TOP
flag to my Intent, that calling startActivity(intent)
would reuse a single Activity instance and give me the Intent in the onNewIntent
callback. I did both of these things, and onNewIntent
never fires and onCreate
fires every time. The docs also say that this.getIntent()
returns the intent that was first passed to the Activity when it was first created. In onCreate
I'm calling getIntent
and I'm getting a new one every time (I'm creating the intent object in another activity and adding an extra to it...this extra should be the same every time if it was returning me the same intent object). All this leads me to believe that my activity is not acting like a "single top", and I don't understand why.
我在 Android 文档中读到,通过将我的 Activity 的 launchMode 属性设置为 singleTop 或通过将FLAG_ACTIVITY_SINGLE_TOP
标志添加到我的 Intent,该调用startActivity(intent)
将重用单个 Activity 实例并在onNewIntent
回调中为我提供 Intent 。我做了这两件事,onNewIntent
从不onCreate
每次都开火和开火。文档还说this.getIntent()
返回首次创建时首先传递给活动的意图。在onCreate
我打电话时getIntent
,我每次都会得到一个新的(我在另一个活动中创建意图对象并添加一个额外的......如果它给我带来相同的回报,这个额外的每次都应该是相同的意图对象)。所有这一切让我相信我的活动不像“单顶”,我不
To add some background in case I'm simply missing a required step, here's my Activity declaration in the manifest and the code I'm using to launch the activity. The Activity itself doesn't do anything worth mentioning in regards to this:
要添加一些背景以防我只是遗漏了一个必需的步骤,这里是清单中的 Activity 声明以及我用来启动 Activity 的代码。Activity 本身在这方面没有做任何值得一提的事情:
in AndroidManifest.xml:
在 AndroidManifest.xml 中:
<activity
android:name=".ArtistActivity"
android:label="Artist"
android:launchMode="singleTop">
</activity>
in my calling 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);
采纳答案by znq
Did you check if onDestroy()
was called as well? That's probably why onCreate()
gets invoked every time instead of onNewIntent()
, which would only be called if the activity is already existing.
你有没有检查是否onDestroy()
也被调用了?这可能就是为什么onCreate()
每次都被调用而不是onNewIntent()
,它只会在活动已经存在时被调用。
For example if you leave your activity via the BACK-button it gets destroyed by default. But if you go up higher on the activity stack into other activities and from there call your ArtistActivity.class
again it will skip onCreate()
and go directly to onNewIntent()
, because the activity has already been created and since you defined it as singleTop
Android won't create a new instance of it, but take the one that is already lying around.
例如,如果您通过后退按钮离开您的活动,默认情况下它会被销毁。但是,如果您在活动堆栈的更高层进入其他活动,并从那里ArtistActivity.class
再次调用您的活动,它将跳过onCreate()
并直接转到onNewIntent()
,因为该活动已经创建,并且由于您将其定义为singleTop
Android 不会创建它的新实例,但拿已经躺在身边的那个。
What I do to see what's going on I implement dummy functions for all the different states of each activity so I always now what's going on:
我做什么来看看发生了什么我为每个活动的所有不同状态实现了虚拟函数,所以我总是现在发生了什么:
@Override
public void onDestroy() {
Log.i(TAG, "onDestroy()");
super.onDestroy();
}
Same for onRestart()
, onStart()
, onResume()
, onPause()
, onDestroy()
onRestart()
, onStart()
, onResume()
, onPause()
,相同 onDestroy()
If the above (BACK-button) wasn't your problem, implementing these dummies will at least help you debugging it a bit better.
如果上述(后退按钮)不是您的问题,那么实现这些假人至少可以帮助您更好地调试它。
回答by Steve B
The accepted answer is not quite correct. If onDestroy() was called previously, then yes, onCreate() would always be called. However, this statement is wrong: "If you go up higher on the activity stack into other activities and from there call your ArtistActivity.class again it will skip onCreate() and go directly to onNewIntent()"
接受的答案并不完全正确。如果之前调用了 onDestroy(),那么是的,将始终调用 onCreate()。但是,这种说法是错误的:“如果您在活动堆栈的更高位置进入其他活动,并从那里再次调用您的 ArtistActivity.class,它将跳过 onCreate() 并直接转到 onNewIntent()”
The "singleTop" section of http://developer.android.com/guide/components/tasks-and-back-stack.htmlexplains plainly how it works (attention to bold text below; I've also proven this through my own debugging):
http://developer.android.com/guide/components/tasks-and-back-stack.html的“singleTop”部分清楚地解释了它是如何工作的(注意下面的粗体文字;我也通过我自己的调试):
"For example, suppose a task's back stack consists of root activity A with activities B, C, and D on top (the stack is A-B-C-D; D is on top). An intent arrives for an activity of type D. If D has the default "standard"launch mode, a new instance of the class is launched and the stack becomes A-B-C-D-D. However, if D's launch mode is "singleTop", the existing instance of D receives the intent through onNewIntent(), because it's at the top of the stack—the stack remains A-B-C-D. However, if an intent arrives for an activity of type B, then a new instance of B is added to the stack, even if its launch mode is "singleTop"."
“例如,假设一个任务的后台堆栈由根活动 A 组成,活动 B、C 和 D 位于顶部(堆栈是 ABCD;D 位于顶部)。对于类型 D 的活动,意图到达。如果 D 具有默认“标准”启动模式,该类的一个新实例被启动并且堆栈变为ABCDD。但是,如果D的启动模式是“singleTop”,则D的现有实例通过onNewIntent()接收意图,因为它在顶部堆栈的——堆栈仍然是 ABCD。然而,如果一个 Intent 到达一个类型为 B 的活动,那么 B 的一个新实例会被添加到堆栈中,即使它的启动模式是“singleTop”。
In other words, starting an activity through SINGLE_TOP will only reuse the existing activity if it is already at the top of the stack. It won't work if another activity in that same task is at the top (for example, the activity that is executing startActivity(SINGLE_TOP)); a new instance will be created instead.
换句话说,通过 SINGLE_TOP 启动一个 Activity 只会重用现有的 Activity 如果它已经在堆栈的顶部。如果同一任务中的另一个活动位于顶部(例如,正在执行 startActivity(SINGLE_TOP))的活动,它将不起作用;将创建一个新实例。
Here are two ways to fix thisso that you get the SINGLE_TOP behavior that you want -- the general purpose of which is to reuse an existing activity, instead of creating a new one...
这里有两种方法可以解决这个问题,以便您获得所需的 SINGLE_TOP 行为——其一般目的是重用现有活动,而不是创建一个新活动......
First way(as described in the comment section of the accepted answer): You could add a launchMode of "singleTask" to your Activity. This would force onNewIntent() because singleTask means there can only be ONE instance of a particular activity in a given task. This is a somewhat hacky solution though because if your app needs multiple instances of that activity in a particular situation (like I do for my project), you're screwed.
第一种方式(如已接受答案的评论部分所述):您可以将“singleTask”的launchMode添加到您的活动中。这将强制 onNewIntent() 因为 singleTask 意味着在给定的任务中只能有一个特定活动的实例。不过,这是一个有点棘手的解决方案,因为如果您的应用程序在特定情况下需要该活动的多个实例(就像我为我的项目所做的那样),那么您就完蛋了。
Second way (better):Instead of FLAG_ACTIVITY_SINGLE_TOP, use FLAG_ACTIVITY_REORDER_TO_FRONT. This will reuse the existing activity instance by moving it to the top of the stack (onNewIntent() will be called as expected).
第二种方式(更好):代替 FLAG_ACTIVITY_SINGLE_TOP,使用 FLAG_ACTIVITY_REORDER_TO_FRONT。这将通过将现有活动实例移到堆栈顶部来重用它(onNewIntent() 将按预期调用)。
The main purpose of FLAG_ACTIVITY_SINGLE_TOP is to prevent the creation of multiple instances of an Activity. For instance, when that activity can be launched via an intent that comes from outside of your application's main task. For internal switching between activities in my app, I've found that FLAG_ACTIVITY_REORDER_TO_FRONT is generally what I want instead.
FLAG_ACTIVITY_SINGLE_TOP 的主要目的是防止创建一个 Activity 的多个实例。例如,当该活动可以通过来自应用程序主要任务之外的意图启动时。对于我的应用程序中活动之间的内部切换,我发现 FLAG_ACTIVITY_REORDER_TO_FRONT 通常是我想要的。
回答by Kodak
Set this flag to your intent:
根据您的意图设置此标志:
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP)