这篇文章本来作为AndroidDeveloper的学习笔记,当初对Android是一无所知,现在的程度是粗浅的看了AMS源码,且读了《Android群英准》和《Android开发艺术探索》后的总结。
Introduction to Activities
Activities是Android四大组件之一,用户可与其提供的屏幕进行交互,以执行拨打电话、拍摄照片、发送电子邮件或查看地图等操作。 每个 Activity 都会获得一个用于绘制其用户界面的窗口。窗口通常会充满屏幕,但也可小于屏幕并浮动在其他窗口之上。
在manifest.xml中的写法为:
<manifest ... >
<application ... >
<activity android:name=".ExampleActivity" />
...
</application ... >
...
</manifest >
Activity Lifecycle
- Entire lifetime (
onCreate()
->onDestroy()
) - Visible lifetime(
onStart()
->onStop()
) - Foreground lifetime(
onResume()
->onPause()
)
整个生命周期和前台生命周期很好理解,那么可见生命周期和前台生命周期有什么区别呢?因为屏幕上可以存在多个Activity,比如在一个Activity1中打开了一个对话框(这个对话框也是一个Activity,记为Activity2),此时用户既可以看到Activity1也可以看到Activity2,此时Activity2处于前台生命周期,Activity1处于可见生命周期。如下图所示,当点击START DIALOGACTIVITY按钮时,MainActivity会调用onPause()方法,而不是onStop()。
完整的生命周期示意图如下图所示:
这里提出一个问题:(也是我面试被问到的)
假设当前Activity为A,如果这时用户打开一个新的Activity B,那么B的onResume和A的onPause哪个先执行呢?
先说答案:A先onPause,B才能onResume
源码中找答案:
mResumedActivity表示当前处于resume状态的Activity,
/**
* Current activity that is resumed, or null if there is none.
*/
ActivityRecord mResumedActivity = null;
/*
此处省略
*/
// If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous activity
// to be paused, while at the same time resuming the new resume activity only if the
// previous activity can't go into Pip since we want to give Pip activities a chance to
// enter Pip before resuming the next activity.
final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0
&& !lastResumedCanPip;
//Pause all activities in either all of the stacks or just the back stacks.
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
if (mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Pausing " + mResumedActivity);
pausing |= startPausingLocked(userLeaving, false, next, false);
}
/// M: onBeforeActivitySwitch @{
mService.mAmsExt.onBeforeActivitySwitch(mService.mLastResumedActivity, next, pausing,
next.getActivityType());
/// M: onBeforeActivitySwitch @}
if (pausing && !resumeWhilePausing) {
if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
"resumeTopActivityLocked: Skip resume: need to start pausing");
// At this point we want to put the upcoming activity's process
// at the top of the LRU list, since we know we will be needing it
// very soon and it would be a waste to let it get killed if it
// happens to be sitting towards the end.
if (next.app != null && next.app.thread != null) {
mService.updateLruProcessLocked(next.app, true, null);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
if (lastResumed != null) {
lastResumed.setWillCloseOrEnterPip(true);
}
return true;
} else if (mResumedActivity == next && next.isState(RESUMED)
&& mStackSupervisor.allResumedActivitiesComplete()) {
// It is possible for the activity to be resumed when we paused back stacks above if the
// next activity doesn't have to wait for pause to complete.
// So, nothing else to-do except:
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
executeAppTransition(options);
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Top activity resumed (dontWaitForPause) " + next);
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
Tasks and Back Stack
Android中的Activity是可以层叠的,没启动一个新的Activity,就会覆盖在原有的Activity之上,然后点击Back键会销毁最上面的Activity,下一个Activity就会重新显示出来。可以思考一下这种层叠的结构怎么实现?没错,就是栈,First in Last out,假设启动顺序为Activity1 -> Activity2 -> Activity3,那么栈中的结构是,Activity3在顶部,Activity1在底部。
When the user presses the Back button:
在Android中,是使用Task来管理Activity的,一个Task就是一个这样的栈结构,这个栈也被称为Back Stack。
launchMode:
- standard(the default mode):每启动一个新的Activity,都会创建一个新的实例
- singleTop:如果启动的Activity已经在栈顶,则不会再创建实例
- singleTask:只要启动的Activity在栈里面,则不会再创建实例,并且这个Activity之上的所有Activity全部出栈,如果没有在栈里面,则创建实例
- singleInstance:这种模式是为了不同的APP能共享Activity,启动的Activity会在一个单独的Back Stack中,并保证不再有其他Activity实例进入,也是说这个Back Stack只有这一个Activity。
这里我画了一个示例图:
关于启动模式,基本的知识就如上述写的,读过《Android群英传》和《Android开发艺术探索》后总结一下两本书中对Activity部分的讲解。
standard
- 每启动一个Activity都会重新创建一个新的实例,不管这个实例是否存在
- 谁启动了这个Activity,那么这个Activity就运行在启动它的那个Activity所在的栈中。比如Activity A启动了Activity B(standard模式),那么B就进入到A的栈中。
singleTop
- 新的Activity已经位于任务栈的栈顶,那么此Activity不会被重新创建(如果不是位于栈顶,新的Activity会重新创建),同时它的onNewIntent方法会被回调。
- 以singleTop启动的Activity的
onCreate
、onStart
不会被系统调用,因为它没有发生改变。
singleTask
- 只要Activity在一个栈中存在,那么多次启动此Activity都不会创建实例
For example:
No1
S1:ABC
Activity D以SingleTask启动,所需任务栈为S2(S2未创建)
系统会先创建S2,然后创建D的实例压入S2中
No2
S1:ABC
Activity D以SingleTask启动,所需任务栈为S1
系统直接创建D的实例压入S1中
No3
S1:ADBC
Activity D以SingleTask启动,所需任务栈为S1
系统不会创建D的实例,将D切换到栈顶,并且clearTop,即D上面的Activity(BC)全部出栈,最终S1的情况为AD
No4
如图所示
Back Stack:12
Background Task:YX
Activity Y以singleTop启动,那么Background Task会切换到Back Stack,整个后退列表变成了YX21,用户按back键的时候,列表中的Activity一一出栈。
singleInstance
- 具有singleTask模式的所有特性
- 此模式启动的Activity只能单独地位于一个任务栈中
面试中常见问题:(掌握的越深越好)
- Activity启动模式
- Activity启动过程
- Activity生命周期