Android系统中Activity的设计是很巧妙的。在内存管理上的设计影响多任务管理在Android系统中运行自如。
Android Task:指的是与用户交互的Activity实例的集合。
Task是以栈的形式存放在,这个栈就是Activity的回退栈。
android:launchMode="standard"
standard是android:launchMode的默认值,无论是android:launchMode=”standard”,还是没有设置android:launchMode属性,Activity都是以standard模式启动的。
细心的同学可以发现,有这样的情景:如果你点击一个控件去执行一次startActivity,如果是一个低性能的Android手机,你在页面没跳转前点了N次,就会发现启动了N个新的Activity,这就是standard模式,这种模式能让你能够创建多个一个新的Activity。
设置了android:launchMode="standard"
的Activity,新生成的实例会放入发送Intent的Task的栈顶部。
跨程序之间调用: 新开启的Activity会放入发送Intent的Task的顶部,虽然他们不是同一个App,但是还不可思议的叠在一起了。
跨应用之间启动Activity,会创建一个新的Task,新生成的Activity就会放入新的Task中。
使用场景: standard可以用在类似于朋友圈发动态的Activity,发一个动态就创建一个Activity。
singleTop和standard基本一样,singleTop拥有standard特性,可以无限创建新的Activity,但是,当且仅当,如果start的Activity已经位于调用Activity所在的Task的栈顶,则不创建新的Activity,而是使用当前的这个Activity实例,并调用这个实例的onNewIntent方法。
注: 如果使用了singleTop,就要处理Activity的onCreate和onNewIntent两个方法,确保逻辑正常。
VActivity.startActivity(new Intent(V.this,VActivity.class)) 前:
VActivity.startActivity(new Intent(V.this,VActivity.class)) 后:
看似没什么变化,其实走了一遍onNewIntent()方法
**使用场景:**singleTop一个典型的使用场景是搜索功能。假设有一个搜索框,每次搜索查询都会将到SearchActivity查看结果,为了更好的交互体验,在结果页顶部也放置这样的搜索框。如果SearchActivity的launchMode设置为standard,意味着每次搜索都要创建一个SearchActivity,有个N个SearchActivity,就要按下N次Back键才能返回,这样的设计是不合理的。
使用singleTop的话,当进行了一次搜索后,SearchActivity会在栈顶。即使有新的搜索需求的时候,也不会创建SearchActivity了,而且Back键只需要按一次即可回到进入搜索前的页面。
singleTask这个模式和其他启动模式很差异很大。singleTask模式的Activity,系统中只会存在一个。如果这个Activity已经创建过了,则intent就会通过onNewIntent传递到这个Activity;如果这个Activity一开始就没创建,那么会被创建。singleTask模式只会在Activity创建后,到能看到其的特点。
AActivity.startActivity(new Intent(AActivity.this,SingleTaskActivity.class))后
MActivity.startActivity(new Intent(MActivity.this,SingleTaskActivity.class))后
可以看得出来: MActivity、LActivity、UActivity都被销毁了,并正常执行了它们销毁时的生命周期(如onDestroy)。最后来到SingleTaskActivity.onNewIntent生命周期内。
不同App的Intent传递时,如果系统中不存在singleTask Activity,那么会创建一个新Task,然后创建SingleTask Activity的,将其放入新的Task中。
如果singleTask Activity所在的App进程存在,但是singleTask Activity不存在,那么从另外一个App启动这个Activity,新的Activity实例会被创建,放入到所属进程所在的Task中,并位于栈顶位置。
如果singleTask Activity存在,从其它App中启动,那么这个singleTask Activity所在的Task会被移到顶部,然后在这个Task中,位于singleTask Activity之上的所有Activity将会被正常销毁。如果按返回键,那么先回退到这个Task中的其它Activity,直到当前Task的Activity回退栈为空时,才会返回到调用App进程中的Task。
The system creates a new task and instantiates the activity at the root of the new task. However, if an instance of the activity already exists in a separate task, the system routes the intent to the existing instance through a call to its onNewIntent() method, rather than creating a new instance. Only one instance of the activity can exist at a time. Although the activity starts in a new task, the BACK key still returns the user to the previous activity.
意思是: 系统会创建一个新的Task,然后singelActivity会放入这个新Task的底部。
写了一个如上图的Demo:
运行到SingleTaskActivity的时候,查看Activity任务栈发现,SingleTaskActivity创建的时候,系统没有创建一个新的Task,而是放入了调用Activity的Task中 。
adb shell dumpsys activity
可以查看Android的Activity任务栈
如图,看到SingleTaskActivity与VActivity、AActivity在同一个栈中。
android:launchMode=singleTask的同时,再设置android:taskAffinity
可以实现启动这个Acitivity时,会创建一个新的Task,再将这个Activity放入新Task中
使用场景: 其实这样的场景不算多也不算少,如果一个App里有社区,那么每个用户的App看到的社区也是一样的,推送进来也会调用这个社区,这里就可以使用singleTask。
singleInstance比singleTask容易理解一些,它和singleTask一样,只会存在一个个这样的Activity。唯一不同的是,存放singleInstance Activity的Task只能存放一个该模式的Activity实例 。如果从singleInstance Activity启动另一个Activity,那么这个Activity会放入其他的Task中;如果singleInstance Activity被别的Activity启动,它也会放入不同于调用Activity的Task中。
基本很少使用,Launcher中可能使用。或者需要使Activity是单例。
启动模式的设置如果不想在manifest中配置,还可以在Intent中设置。
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
this.startActivity(new Intent(this,SingleTopActivity.class));