SINGLE_TOP | CLEAR_TOP似乎工作95%的时间。为什么5%? [英] SINGLE_TOP | CLEAR_TOP seem to work 95% of the time. Why the 5%?

查看:156
本文介绍了SINGLE_TOP | CLEAR_TOP似乎工作95%的时间。为什么5%?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个几乎完成的应用程序有一个不平凡的活性结构。有与此应用程序相关的推送通知,并选择通知项能为我们带来了一个特殊的活动,无论应用程序是否前景/背景/不活跃。

I have a nearly-finished application with a non-trivial activity structure. There are push notifications associated with this app, and selecting the notification entry is supposed to bring up a specific activity regardless of whether the app is foreground/background/not active.

如果应用程序是不活跃的,我已经能够成功地启动应用程序,并自动导航到相应的部分。然而,当应用程序是活动的,我有一个问题。我将present问题的简化版本,沟通的问题的性质,并在需要时我会后我的应用程序的活动结构和相关的code的细节(实际上,工作现在)。

If the app is not active, I have been able to successfully start the app and auto-navigate to the appropriate part. However, when the app is active, I have a problem. I will present a simplified version of the issue, to communicate the nature of the problem, and I will post the details of my app's activity structure and relevant code as needed (actually, working on that now).

所以,我的应用程序的活动栈(大大简化)看起来是这样的:

So, my app's activity stack (greatly simplified) looks like this:

A - > B - > X

A -> B -> X

其中,A,根系活力,是一个登录页面; B是东西主页和X是若干的活动之一,可以从主页开始(但只有一个实例活性的时间;由于这些只能从乙开始)。

Where A, the root activity, is a login page; B is something of a "home page" and X is one of several activities that can be started from the home page (but only one instance active at a time; as these can only be started from B).

在选择通知,我需要的应用程序自动定位到B,不管是什么状态,它是在事前 - 无论是[A],[A - > B],[A - > B - > X]或[](应用程序未激活)。

When the notification is selected, I need the application to automatically navigate to B, regardless of what state it was in beforehand - whether [A], [A -> B], [A -> B -> X] or [ ] (app not active).

我的通知传递的意图,活动答:我已经使用CLEAR_TOP和NEW_TASK标志试过了,没有。当前有launchmode = singleTask。这样做,我想我解决所有可能存在的堆栈配置,并将其降低为[A]。的意图还携带一个额外的标识它作为从通知的到来,而不是通常的发射

My notification passes an Intent to activity A. I have tried using CLEAR_TOP and NEW_TASK flags, and none. A currently has launchmode=singleTask. Doing this, I figure I am addressing all possible existing stack configurations and reducing them to [A]. The Intent also carries an extra which identifies it as coming from a notification, as opposed to a usual launch.

活动A,在识别的意图从发送通知(它可以在两个的onCreate()和onNewIntent()做到这一点),发送意向到活动B.此意图包含CLEAR_TOP和SINGLE_TOP。 B有launchmode = singleTop。

Activity A, upon identifying the Intent as being sent from the notification (it can do this in both onCreate() and onNewIntent() ), sends an Intent to Activity B. This Intent contains CLEAR_TOP and SINGLE_TOP. B has launchmode=singleTop.

95%的时间,这可以作为理想的,并经过pressing通知,应用程序的堆栈是[A - > B]。 大致的5%的时间,该应用不知何故结束与一叠[A - > B - > B〕。

95% of the time, this works as desired, and after pressing the notification, the app's stack is [A -> B]. Roughly 5% of the time, the app somehow ends up with a stack of [A -> B -> B].

在这里发生了什么,或者什么,我做错了什么?任何想法

Any ideas on what's happening here, or anything I'm doing wrong?

我会后更详细的,如果这原来是一个不平凡的问题。事实上,发布更多的细节现在...

I'll post more detail if this turns out to be a non-trivial problem. In fact, posting more details now...

~~~~~~~~~~~~~~~~~~~~~~~更详细~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~

~~~~~~~~~~~~~~~~~~~~~~~MORE DETAIL~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

通过调试器步进表明,每一次将其意图B,B的现有实例的onDestroy()'d为的onCreate()之前'D,然后也有其onNewIntent()调用。这似乎很奇怪,我和建议,无论是我误会我使用(CLEAR_TOP和SINGLE_TOP),或别的东西干扰了他们。标志

Stepping through the debugger shows that, every time A sends its intent to B, the existing instance of B is onDestroy()'d before being onCreate()'d and then also having its onNewIntent() called. This seems odd to me, and suggests that either I misunderstand the flags I am using (CLEAR_TOP and SINGLE_TOP), or something else is interfering with them.

我还没有复制成功调试错误的堆栈结构。不知道是否是因为它不会发生在调试,还是我只是还没有尝试过足够的时间。

I have not successfully reproduced the erroneous stack structure in debug. Not sure if it's because it doesn't happen in debug, or I just haven't tried enough times.

code的意图:

在C2DM接收服务:

protected void onMessage(Context context, Intent intent) {
    int icon = R.drawable.some_drawable;
    CharSequence tickerText = "blah";
    long when = System.currentTimeMillis();
    Notification notification = new Notification(icon, tickerText, when);

    //Context context = getApplicationContext(); //Don't need this; using the context passed by the message.
    CharSequence contentTitle = intent.getStringExtra("payload");
    CharSequence contentText = "Lorem ipsum dolor si amet,";
    Intent notificationIntent = new Intent(this, LoginPage.class);
    //notificationIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); //Tried with and without
    notificationIntent.putExtra(PushManager.PUSH_INTENT, PushManager.PUSH_INTENT); //Indicator that this was send from notification

    PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
    notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);

    notificationManager.notify(PushManager.ALARM_NOTIFICATION_ID, notification);
}

在LoginPage(活动A),登录成功后:

In LoginPage (Activity A), after successful login:

Intent i = new Intent(LoginPage.this, TabHomePage.class);
// (If we're automatically going to tab 2, inform next activity)
if(fromNotification) {
    i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
    i.putExtra(TabHomePage.TAB_NUMBER, TabHomePage.TAB_2);
}
startActivity(i);

有关活动的协议栈结构更详细的,这里的图片:

For more detail on the activity stack structure, here's the picture:

<一个href="http://i89.photobucket.com/albums/k207/cephron/ActivityStack.png">http://i89.photobucket.com/albums/k207/cephron/ActivityStack.png

和这里的万语千言:

活动A是一个登录页面;成功登录后,它开始B. B是一个TabActivity,其中包含在其内(由C,D,E psented重新$ P $)三项活动。 每个C,D和E的实际上是一个的ActivityGroup其子活动模仿活动的惯常堆栈行为。

Activity A is a login page; upon successful login, it starts B. B is a TabActivity, which contains three Activities within it (represented by C, D, E). Each of C, D, and E is actually an ActivityGroup whose child Activities mimic the usual stack behaviour of Activities.

因此​​,每个标签包含其自身的活动栈,这些栈的目前正在推到/从由使用者的导航弹出标签的变化之间的切换(每个标签包含一个堆栈ListActivities通过实体的分级结构浏览的)。这些也可以启动超越巨人'B'TabActivity新的活动(再利用X psented $ P $)。

So, each tab contains its own stack of activities, and switching between tabs changes which of these stacks is currently being pushed to/popped from by the user's navigation (each tab contains a stack of ListActivities browsing through a hierarchical structure of entities). These can also start new activities beyond the giant 'B' TabActivity (represented by X).

所以,在从活动日志记录中,创建至少有三个活动之前,多个用户输入被接受: -B被创建(和被看见,因为TabWidget的,现在在屏幕的顶部) 创建ActivityGroups - 酮:哪一个属于默认选项卡。此的ActivityGroup保持psented在屏幕上unre $ P $然而......只显示子活动其堆栈的顶部的活性。 -so,最后,所创建的ActivityGroup堆栈的根的活性(图中,F是这样的活动的一个例子)。该活动展示了TabWidget低于本身。

So, upon logging in from Activity A, at least three activities are created before more user input is accepted: -B is created (and is seen, because of the TabWidget now at the top of the screen) -One of the ActivityGroups is created: whichever one belongs to the default tab. This ActivityGroup remains unrepresented on screen, however...it only shows the top activity of its stack of child activities. -So, finally, the "root" activity of that ActivityGroup's stack is created (in the picture, F is an example of such an Activity). This Activity shows itself below the TabWidget.

在每个选项卡已经去过一次,没有创建更多的活动/毁于选项卡之间切换(不包括内存杀死)。 pressing回任何标签光洁度()。ES的活性在该堆栈的顶部,示出它下面的之一。 pressing从任何选项卡中的根系活力(如F)回完成整个TabActivity,将用户发送回A。

After each tab has been visited once, no more Activities are created/destroyed by switching between tabs (not counting memory kills). Pressing back in any tab finish()es the Activity at the top of that stack, showing the one beneath it. Pressing back from the root activity (like F) in any tab finishes the whole TabActivity, sending the user back to A.

传递给还B中的意图指示它自动导航到不同的选项卡不是默认的。在我们结束与一个叠层的情况下,[A - > B - >乙〕,第一个B被导航到正确的标签,并且第二个是在默认

The intent passed to B also instructs it to automatically navigate to a different tab than the default. In the case where we end up with a stack of [A -> B -> B], the first B is navigated to the correct tab, and the second is at the default.

推荐答案

TL; DR;同时不要使用CLEAR_TOP与SINGLE_TOP

如果它仅产生的时间误差5%时,很可能是一个并发问题。你说你有SINGLE_TOP | CLEAR_TOP用于呼叫活动B. CLEAR_TOP破坏活性B的当前实例和意图被递送到的onCreate()。 SINGLE_TOP不破坏活动B的当前实例,并提供意图onNewIntent()。

If it only produces an error 5% of the time, it is likely to be a concurrency issue. You said you have SINGLE_TOP | CLEAR_TOP for calling Activity B. CLEAR_TOP destroys the current instance of Activity B and the intent is delivered to onCreate(). SINGLE_TOP doesn't destroy the current instance of Activity B, and delivers the intent to onNewIntent().

在SINGLE_TOP标志首先读取,意图传递到活动的B调用onNewIntent()当前实例。然后CLEAR_TOP读取和活动B被破坏,新的实例与的onCreate()创建的,一切工作正常。

When the SINGLE_TOP flag is read first, the intent is delivered to the current instance of Activity B calling onNewIntent(). Then CLEAR_TOP is read and Activity B is destroyed and a new instance is created with onCreate() and everything works fine.

在CLEAR_TOP是第一次读,活动B的现有实例被破坏,新的用的onCreate()创建。然后SINGLE_TOP被读取,并且意图被输送到onNewIntent()为好。此外,它的作品了。

When CLEAR_TOP is read first, the existing instance of Activity B is destroyed and a new one is created with onCreate(). Then SINGLE_TOP is read and the intent is delivered to onNewIntent() as well. Again, it works out.

在CLEAR_TOP和SINGLE_TOP读取的同时,当前的活动实例被破坏,CLEAR_TOP调用的onCreate()和SINGLE_TOP调用的onCreate()为好,因为活动的B没有实例存在的时刻。因此,你最终A-> B->乙。

When CLEAR_TOP and SINGLE_TOP are read at the same time, the current instance of activity is destroyed and CLEAR_TOP calls onCreate() and SINGLE_TOP calls onCreate() as well, because no instance of Activity B exists at the moment. Thus, you end up with A->B->B.

这篇关于SINGLE_TOP | CLEAR_TOP似乎工作95%的时间。为什么5%?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆