栈结构
我们先来简单聊聊什么是栈吧:
栈作为一种常见的线性数据结构,具有仅栈顶元素可见与LIFO后进先出的特性。
栈是一种非常简单的数据结构,方法也很少,常用的就是三种:push入栈 pop出栈 peek查看栈顶元素。
借用一张图,清晰明了:
当然,栈其实就是一种抽象概念,一般我们都是用数组表或者是单链表来实现。
在Android中,我们常用任务栈(Task)来管理一个或多个Activity。
优点:
1.程序打开时就创建了一个任务栈,用于存储当前程序的activity(没有特定指明taskAffinity),当前程序(包括被当前程序所调用的)所有的activity属于一个任务栈。
2.一个任务栈包含了一个activity的集合,可以有序的选择哪一个activity和用户进行交互,只有在任务栈栈顶的activity才可以跟用户进行交互。
3.任务栈可以移动到后台,并且保留了每一个activity的状态,并且有序的给用户列出它们的任务,而且还不丢失它们状态信息。
4.退出应用程序时,会把所有的任务栈中所有的activity清除出栈时,任务栈会被销毁,程序退出。
缺点:
1.每开启一次页面都会在任务栈中添加一个Activity,而只有任务栈中的Activity全部清除出栈时,任务栈被销毁,程序才会退出,这样就造成了用户体验差,需要点击多次返回才可以把程序退出了。
2.每开启一次页面都会在任务栈中添加一个Activity,会造成数据冗余,重复数据太多,极端情况下会导致内存溢出的问题(OOM)。
Standard--标准模式
Android 创建Activity 时的默认模式,假设没有为Activity设置启动模式的话,默认就是标准模式。每次启动一个activity都会又一次创建一个新的实例入栈,无论这个实例是否存在。
SingleTop--栈顶复用模式
栈顶复用模式分两种情况处理:当需要创建的Activity已经处于栈顶时,此时会直接复用该栈顶的Activity,不会创建新的;当需要创建的Activity不处于栈顶时,此时便会创建一个新的Activity入栈,此时同Standard模式一样。
若栈顶Activity被直接复用时,它的onCreate、onStart方法均不会被系统调用,由于它没有发生改变,一个新的方法 onNewIntent会被回调(Activity被正常创建时不会回调此方法)。
SingleTask--栈内复用模式
栈内复用模式:若需要创建的Activity已经处于栈中,此时不会创建新的Activity,而是将存在栈中的Activity上面的其他Activity全部出栈销毁,使它成为栈顶。
此时得到复用的Activity 会回调onNewIntent方法,然后走onRestart方法流程,被销毁的Activity的onDestroy方法亦会执行。
SingleInstance--单实例模式
指定为SingleInstance模式的Activity会启用一个新的返回栈来进行管理,不管哪个应用程序来访问这个活动,都共用同一个返回栈,从而解决了共享活动实例的问题。
这个模式经常应用于系统中的应用,比如Launcher、锁屏应用等等,整个系统中仅仅有一个。比方Activity A是该模式,启动 A 后,系统便会为它创建一个单独的任务栈,由于栈内复用的特性,其余的请求均不会创建新的Activity,除非这个独特的任务栈被系统销毁。
每个Activity都有taskAffinity属性,这个属性指出了它希望进入的Task,如果一个Activity没有显式的指明该Activity的taskAffinity,那么它的这个属性就等同于Application指明的taskAffinity,如果 Application也没有指明,那么该taskAffinity的值就等同于包名,而Task也有自己的affinity属性,它的值等于它的根Activity的taskAffinity的值。
上述的四种Activity 启动模式均可在 Manifest.xml中通过 launchMode来指定,同时,我们亦可在启动Activity时,为启动的intent动态添加一个flag来指定其启动模式。
要注意的是,动态指定方式的优先级要高于静态指定方式。
FLAG_ACTIVITY_NEW_TASK
1.FLAG_ACTIVITY_NEW_TASK标签必须配合taskAffinity属性使用,如果不设置taskAffinity属性值,将不会生成新task,其效果与标注模式-Standard启动无差异。
2.当从启动模式为singleInstance的Acitivity中启动新的Acitivity时,新的Activity自带FLAG_ACTIVITY_NEW_TASK标签。
3.首先会查找是否存在和被启动的Activity具有相同的亲和性的任务栈(即taskAffinity,注意同一个应用程序中的activity的亲和性一样),如果有,则直接把这个栈整体移动到前台,并保持栈中的状态不变,即栈中的activity顺序不变,如果没有,则新建一个栈来存放被启动的activity。
FLAG_ACTIVITY_SINGLE_TOP
作用是为Activity指定 “SingleTop”启动模式,与在Android Mainfest.xml指定效果同样。
FLAG_ACTIVITY_CLEAN_TOP
具有此标记位的Activity,启动时会将与该Activity在同一任务栈中的其他Activity出栈。一般与SingleTask启动模式一起出现,事实上SingleTask启动模式默认具有此标记位的作用。
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
具有此标记位的Activity不会在历史Activity的列表中出现,当某些情况下我们不希望用户通过历史列表回到Activity时,此标记位便体现了它的效果。