由从服务中启动activity——谈谈安卓的任务与栈
在安卓的服务中这样启动活动:
你会得到这样的错误:
你知道我对安卓的什么地方最为痴迷?是它应用之间的协作。怎么协作?依靠activity之间的协作。
这种协作是可以跨越应用的。我们从task谈起。
task最直观的是安卓第三个虚拟键所列出的那些就是任务。
以上这种功能的实现,要从task谈起,developer上,这样定义task:
翻译过来,大体意识就是task是一个具有栈结构的容器,用以执行一定特定的工作,它可以放置多个Activity实例。
启动一个应用,系统就会为之创建一个task,来放置根Activity。默认情况下,一个Activity启动另一个Activity时,两个Activity是放置在同一个task中的,后者被压入前者所在的task栈,当用户按下后退键,后者从task被弹出,前者又显示在幕前,特别是启动其他应用中的Activity时,两个Activity对用户来说就好像是属于同一个应用。
task可以分为系统task和task。这两者之间是互相独立的。
当我们运行一个应用时,按下Home键回到主屏,启动另一个应用,这个过程中,之前的task被转移到后台,新的task被转移到前台,其根Activity也会显示到幕前,过了一会之后,在此按下Home键回到主屏,再选择之前的应用,之前的task会被转移到前台,系统仍然保留着task内的所有Activity实例,而那个新的task会被转移到后台,如果这时用户再做后退等动作,就是针对该task内部进行操作了。
一个Activity当然要表面自己身在哪个task,所以每个Activity都有taskAffinity属性。这个属性指出了它希望进入的Task。
如果一个Activity指明自己的taskaffinity,那么它的这个属性就等于Application指明的taskAffinity,如果Application也没有指明,那么该taskAffinity的值就等于包名。
而Task也有自己的affinity属性,它的值等于它的根Activity的taskAffinity的值。
显示的声明activiy的属性
这很简单,在AndroidManifest.xml中声明
有了上面的基础,请记住这两种文档说明的情况:
1. 如果该Activity的allowTaskReparenting设置为true,它进入后台,当一个和它有相同affinity的Task进入前台时,它会重新宿主,进入到该前台的task中。
**2. 如果加载某个Activity的intent,Flag被设置成FLAG_ACTIVITY_NEW_TASK时,它会首先检查是否存在与自己taskAffinity相同的Task,如果存在,那么它会直接宿主到该Task中,如果不存在则重新创建Task。 **
activity有四种启动模式,分别为 standard,singleTop,singleTask,singleInstance。
这四种模式我不细说,我们只从名字上分析分析。
第一种,标准模式,想想就知道是平常的模式,这里的标准意思是每生成一个activity的实例,就当一个实例的放在栈里。
第二种,singleTop,在于那个top。要是activity不在栈顶,它和standard模式没什么区别,要是在top,就不创建一个新的,用栈顶原来那个。
第三种,不那么容易,尤其是 官网的说法好像有问题。
singleTask模式的Activity只允许在系统中有一个实例。 如果系统中已经有了一个实例,持有这个实例的任务将移动到顶部,同时intent将被通过onNewIntent()发送。如果没有,则会创建一个新的Activity并置放在合适的任务中。
这话的意思,我们分两种情况讨论,一是在同一个应用,二是不同。
在同一个应用中,如果系统中还没有singleTask的Activity,会新创建一个,并放在同一任务的栈顶。但是如果已经存在,singleTask Activity上面的所有Activity将以合适的方式自动销毁,让我们想要显示的Activity处于栈顶。
在非同一个应用中,intent是从另外的应用发送过来。系统中没有任何Activity的实例的化,会创建一个新的任务,并且新的Activity被作为根Activity创建;如果系统中拥有这个singleTask的应用存在,新建的Activity会置于这个任务的上面。
第四种,和第三种很像,关键在于singleInstance,就是只能有这一个单例存在在栈中。
回到开头,我们还没解决开始的错误。最简单粗暴的方法是:
这可以解决问题,不过也还存在一个小问题,留待读者发现:)
Flag的字面意思很好理解,如果你读懂了上述的任务与活动启动模式的化,再提供几个intent Flags:
至于意思,还是字面理解就好了。