在Android设计中遇到这样一个问题:
Activity A,在AndroidManifest.xml中设置它的一个<inter-filter>为
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
A的launchMode为“singleTask”。
Activity B,设置launchMode为“standard”。
这样,A作为启动应用的入口Activity;在A中进行某个操作可以跳转到B。
如果此时,点击‘Home’键返回到Home Screen后,再次点击应用图标进入应用,出现的界面为A,而非B。通过一些测试,发现,在重新进入应用时,在Back stack中,位于A之上的其他Activity均被销毁了。
我希望改变这种用户体验,让用户在重新进入时可以看到B,如何做呢?
为了实现这个目标,先了解了Android中和Activity,Task,Back stack有关的内容。下面先列出对解决问题有帮助的资料:
1.区分Activity的四种加载模式
这个web,简明地用示例对Activity的四种launchMode做了说明。在没有阅读官方文档前,对launchMode的入门理解很有帮助。而对Activity,Task,Back stack有了一定认识后,再次阅读,也看出了之前没有理解的东西。
2.官方文档
位于docs/guide/topics/manifest/activity-element.html#lmode下的内容,解释对AndroidManifest.xml中设置activity的launchMode设置。
位于docs/guide/topics/fundamentals/tasks-and-back-stack.html下的内容,解释“Tasks and Back Stack“。
3.Android Activities and Tasks series – An introduction to Android’s UI component model(http://blog.akquinet.de/2010/02/17/android-activites-and-tasks-series-an-introduction-to-androids-ui-component-model/)
这个blog比较完整地和Activity,task有关的内容。下面贴出它的前言部分:
With Android, Google implemented its very own UI component model, introducing various new terms and concepts probably unfamiliar to most developers. Although well designed and powerful, it is unconventional, has a high learning curve and, in some respects, lacks sufficient documentation. Basic use cases may be quick to implement, but in order to develop more complex applications, a thorough understanding of Android’s UI component model is essential.
This series aims at providing this understanding while focusing on the UI related concepts of activities and tasks.
Overview
This series is composed out of four posts:
- This first post gives an introduction to Android’s UI component model and briefly explains the concepts behind activities and tasks.
- The second post details the various intent flags used to customize the start of activies and influence corresponding behavior ( caller).
- The third post deals with the different activity properties specifyable for the called activity ( callee).
- The fourth post concludes the series with an exploration of the different combinations of intent flags and activity properties.
另外,这个blog中还提供了一个应用,用以帮助理解Intent flag。
4.解开Android应用程序组件Activity的"singleTask"之谜
此blog的作者描述了他通过源码研究过程,主要讨论的是当Activity的launchMode为singleTask时,分配Task的问题。作者的结论如下:
至此,我们总结一下,设置了"singleTask"启动模式的Activity的特点:
1. 设置了"singleTask"启动模式的Activity,它在启动的时候,会先在系统中查找属性值affinity等于它的属性值 taskAffinity的任务存在;如果存在这样的任务,它就会在这个任务中启动,否则就会在新任务中启动。因此,如果我们想要设置 了"singleTask"启动模式的Activity在新的任务中启动,就要为它设置一个独立的taskAffinity属性值。
2. 如果设置了"singleTask"启动模式的Activity不是在新的任务中启动时,它会在已有的任务中查看是否已经存在相应的Activity实 例,如果存在,就会把位于这个Activity实例上面的Activity全部结束掉,即最终这个Activity实例会位于任务的堆栈顶端中。
这个blog中,让我了解了‘adb shell dumpsys activity’的使用。这可以将系统中和activity有关的一些内容转储出来。
最后,下面这个web中,提问者的问题和我想解决的是一致的。
Android: bug in launchMode=“singleTask”? -> activity stack not preserved
回答者renchenyu的答复给出了解决的思路:
This is not a bug. When an existed "singleTask" activity is launching, all other activities above it in the stack will be destroyed.
When you press HOME and launch the activity again, ActivityManger calls an intent{act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flat=FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_RESET_IF_NEEDED cmp=A}, so the result is A > B > HOME > A.
It's different when A's launchMode is "Standard". The task which contains A will come to the foreground and keep the state the same as before.
You can create a "Standard" activity eg. C as the launcher and startActivity(A) in the onCreate method of C
OR
Just remove the launchMode="singleTask" and set FLAG_ACTIVITY_CLEAR_TOP|FLAG_ACTIVITY_SINGLE_TOP flag whenever call an intent to A