Tasks and Back Stack

一. 起因: 

遇到一个bug, 从应用A用intent调起应用B的两个Activity, B1和B2的时候, 会遇到如下bug:

二. 复现步骤:

启动A, A调起B1, home, 启动A, A调起B2, 启动A, A调起B1.

这样bug出现, 第二次调起B1的时候, 出现的是B2的界面. 以后一直调起B1, 出现的都是B2的界面.

发现在后面每次调起B1的时候会有log:

Class not found when unmarshalling: com.XXX.XXX

java.lang.ClassNotFoundException: com.XXX.XXX

at java.lang.Class.classForName(Native Method)

......

03-14 15:01:43.108  1897  4129 E Parcel  :... 19 more

03-14 15:01:43.108  1897  4129 E Parcel  : Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack trace available

三. 解决办法: 

我在A启动B的时候, 将

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

改为用:

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

四. 原因

启动A单独作为一个task启动, 然后当A启动B1的时候, B1新建一个task, 包名命名com.B. 当A启动B2的时候, 需要放在另一个task中, 但是发现了此时有com.B (因为B1和B2是属于同一个app, 包名一样都是com.B, 会放在同一个task中). 因而在task com.B中又放了一个B2. 此时此task中有B1, B2. 栈顶是B2. 当A又试图发intent启动B1的时候, 由于是 FLAG_ACTIVITY_NEW_TASK格式的(类似singleTask), 因而只要B1的实例在com.B中存在, 就不会再实例化, 因而会将 com.B 这个task拿到前面, 但是此时这个task里的栈顶是B1. 因而会报错, 并且我们看到的界面是B2, 并且以后无论用同样方法启动B1多少次, 都看到的是B2.

改成加了Intent.FLAG_ACTIVITY_CLEAR_TOP后, A再次启动B1的时候, com.B这个task里会将在B1顶部的所有实例都销毁掉, 所以task里就只有B1了, 这时B1可以启动并且没有错误了, 看到的当前Activity也是B1.

五. 知识点

https://developer.android.com/guide/components/activities/tasks-and-back-stack.html

1. task: 

A task is a collection of activities that users interact with when performing a certain job. 

The device Home screen is the starting place for most tasks. When the user touches an icon in the application launcher (or a shortcut on the Home screen), that application's task comes to the foreground. If no task exists for the application (the application has not been used recently), then a new task is created and the "main" activity for that application opens as the root activity in the stack.

A task is a cohesive unit that can move to the "background" when users begin a new task or go to the Home screen, via the Home button.

通常, 用户从桌面的图标启动一个app, 就是一次task的开始. 

2. launch mode: 

Using the manifest file

When you declare an activity in your manifest file, you can specify how the activity should associate with tasks when it starts.

Using Intent flags

When you call startActivity(), you can include a flag in the Intent that declares how (or whether) the new activity should associate with the current task.

As such, if Activity A starts Activity B, Activity B can define in its manifest how it should associate with the current task (if at all) and Activity A can also request how Activity B should associate with current task. If both activities define how Activity B should associate with a task, then Activity A's request (as defined in the intent) is honored over Activity B's request (as defined in its manifest).

两种方法改变launch mode: 1 写在manifest里, 2 在intent中设置flag. 如果二者都设置了, 以intent中的flag为准.

3. manifest里的值:

standard(default): 创建新activity的实例放在当前task中, 并且一个activity可以实例化多次, 每个实例可能属于不同的task, 一个task里可能包含多个实例.

singleTop: 和standard一样, 特别的是: 如果当前task的栈顶是这个activity的实例, 那么就不新建实例了. 

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 throughonNewIntent(), 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".

singleTask: The system creates a new task and instantiates the activity at the root of the new task. 但是, 如果这个activity的实例已经在其他task中存在了, 那么不会创建新的实例, 用已有的实例. 就是, 同一时间只能存在一个实例.

singleInstance: 和singleTask一样, 但是这个activity is always the single and only member of its task; any activities started by this one open in a separate task. 这个task中只有着一个activity

4. flag的值:

FLAG_ACTIVITY_NEW_TASK:   在新的task里开始一个Activity的实例. 如果task已经存在, 那么这个task被 brought to the foreground. 类似singleTask.

FLAG_ACTIVITY_SINGLE_TOP:  类似singleTop

FLAG_ACTIVITY_CLEAR_TOP: If the activity being started is already running in the current task, then instead of launching a new instance of that activity, all of the other activities on top of it are destroyed and this intent is delivered to the resumed instance of the activity (now on top), through onNewIntent()).

FLAG_ACTIVITY_CLEAR_TOPis most often used in conjunction withFLAG_ACTIVITY_NEW_TASK. When used together, these flags are a way of locating an existing activity in another task and putting it in a position where it can respond to the intent.



总结:

系统提供了两种切换: 

第一种是在AndroidManifest.xml文件中声明Activity自身的启动属性, 另一种是启动时给intent中添加不同的flag.

前者包括:

android:launchMode=standard/singleTop/singleTask/singleInstance

android:clearTaskOnLaunch=true/false

android:finishOnTaskLaunch=true/false

android:allowTaskReparent=true/false

后者包括:

Intent.FLAG_ACTIVITY_NEW_TASK

Intent.FLAG_ACTIVITY_RESER_TASK_IF_NEEDED

Intent.FLAG_ACTIVITY_CLEAR_TOP

Intent.FLAG_ACTIVITY_REORDER_TO_FRONT

Intent.FLAG_ACTIVITY_NO_HISTORY

Intent.FLAG_ACTIVITY_SINGLE_TOP

功能分为三类, 第一类是为了完成在Task之间切换,  第二类是完成在当前Task中改变Activity的顺序, 第三类是为了在Task切换时Task内部重排所属的Activity

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容

  • 原文地址:http://developer.android.com/guide/components/tasks-...
    l_genius阅读 587评论 0 0
  • 今天,学习一下六个帽子学习法,顾名思义,是指使用六种不同颜色的帽子代表不同的思维方式,这些思维方式任何人都有能力掌...
    snailwww阅读 2,256评论 0 4
  • 对不起。 不接受。 大概被伤害的人都是善良的吧,纠结于自己是不是太过冷漠,是不是应该为他考虑,又或者别人的做法有什...
    薄荷味彩铅阅读 209评论 0 0
  • 我和大多数人一样,经常用微博、空间、贴吧这种社交平台。但是后来又陆陆续续戒掉了——或者说是放弃了,因为它们完完全全...
    青山遥也阅读 358评论 5 3