Activity 总结
1、activity生命周期
生命周期方法:onCreate onStart onResume onPause onStop onDestroy
activity A 跳转到activity B的回调
A.onPause -> B.onCreate -> B.onStart -> B.onResume -> A.onStop -> A.onDestroy(A.onDestroy被回收的时候才会调用)
image
2、activity的启动模式
四种启动模式:standard、singleTop、singleTask、singleInstance
standard:
标准模式,系统默认的启动模式。每次启动一个Activity都会重新创建一个新的实例,不管这个实例是否已经存在,它的onCreate、onStart、onResume都会被调用。在这种模式下,谁启动了这个Activity,那么这个Activity就运行在那个启动它的那个Activity所在的任务栈中。一种特殊的情况,当我们用ApplicationContext去启动standard模式的Activity的时候会报错,错误如下:
E/AndroidRuntime(674): android.util.AndroidRuntimeException: Calling startActivity
from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag.
Is this really what you want?
singleTop:
栈顶复用模式。在这种模式下,如果新的Activity已经位于任务栈的栈顶,那么此Activity不会被重新创建,同事它的onNewIntent方法会被调用,通过此方法的参数我们可以取出当前请求的信息。需要注意的是,这个Activity的onCreate、onstart不会被调用。如果这个Activity的实例已经存在但不是位于栈顶,那么新的Activity仍然会重新创建。
举个例子:假设目前栈内的情况为ABCD,其中ABCD为4个activity,A位于栈底,D位于栈顶,假设这个时候要再次
启动D,如果D的启动模式为singleTop,那么栈内的情况仍然为ABCD;如果D的启动模式为standard,那么D会被
重新创建,导致栈内的情况变成ABCDD。
singleTask
栈内复用模式。这是一种单实例模式,在这种模式下,只要Activity在一个栈中存在,那么多次启动此Activity都不会重新创建实例,和singleTop一样,系统也会回调onNewIntent。具体一点,当一个具有singleTask模式的Activity请求启动后,比如Activity A,系统首先会寻找是否存在A想要的任务栈,如果不存在,则重新创建一个任务栈,然后创建A的实例后把A放到栈中。如果存在A所需的任务栈,这时要看A是否在栈中有实例存在,如果有实例存在,那么系统就会把A调到栈顶并调用A的onNewIntent方法,如果实例不存在,就创建A的实例并把A压入栈中。举几个例子:
例子1:
比如目前任务栈S1中的情况为ABC,这时候Activity D以singleTask模式请求启动,其所需要的任务栈为S2,
由于S2和D的实例均不存在,所以系统会先创建任务栈S2,然后再创建D的实例并将其压入任务栈S2。
例子2:
比如目前任务栈S1中的情况为ABC,这时候Activity D以singleTask模式请求启动,其所需要的任务栈为S1,
由于D所需要的任务栈S1存在,所以系统创建D的实例并将其压入任务栈S1。
例子3:
如果D所需要的任务栈为S1,当前任务栈S1中的情况为ADBC,这时候Activity D以singleTask模式请求启动,根
据栈内复用原则,此时D不会重新创建,系统会把D切换到栈顶并调用其onNewIntent方法,同时由于singleTask
默认具有clearTop的效果,会导致栈内所有在D上面的Activity全部出栈,于是最终S1任务中的情况为AD。
singleInstance
单实例模式。这是一种加强的singleTop模式,它除了具有singleTask模式的所有特性外,还加强了一点,那就是具有此种模式的Activity只能单独存在一个任务栈中,换句话说,比如Activity A是singleInstance模式,当A启动后,系统会为它创建一个新的任务栈,然后A独自在这个新的任务栈中,由于栈内复用的特性,后续的请求均不会创建新的Activity,除非这个任务栈销毁了。
3、TaskAffinity和allowTaskRaprenting属性
TaskAffinity
TaskAffinity可以用来控制activity所属的任务栈,但是需要设置activity的启动模式为singleTask或singleInstance才能生效。
<activity android:name=".bActivity"
android:launchMode="singleTask"
android:taskAffinity="taskName"/>
allowTaskRaprenting
allowTaskRaprenting这个属性用于设定Activity能够从启动它的任务中转移到另一个与启动它的任务有亲缘关系的任务中,转移时机是在这个有亲缘关系的任务被带到前台的时候。如果设置了true,则能够转移,如果设置了false,则这个Activity必须要保留在启动它的那个任务中。举个例子
当应用A启动了应用B的某个activity后,如果这个Activity的allowTaskRaprenting属性为true的话,那么当
应用B被启动后,此Activity会直接从应用A的任务栈转移到应用B的任务栈中。
4、android 横竖屏切换
1. 屏幕不旋转
在AndroidManifest文件中的对应Activity中配置android:screenOrientation=”landscape”(横屏,portrait是竖屏);
2. 屏幕旋转时不重新走生命周期
在AndroidManifest文件中的对应Activity中配置android:configChanges="keyboardHidden|orientation|screenSize",最好这三个都配置,否则不能适配所有机型或sdk版本。
默认情况下,屏幕会旋转并且会重新走生命周期。
切横屏,生命周期方法走一遍,切竖屏,生命周期方法走两遍 (用华为mate7测试,切竖屏也是走一遍生命周期)
5、Activity优先级
Activity按照优先级从高到底,分为三种:
- 前台Activity--正在与用户交互的Activity,优先级最高
- 可见但非前台Activity--比如Activity弹出了一个对话框
- 后台Activity --已经被暂停的Activity,比如执行了onStop方法,优先级最低