牛骨文教育服务平台(让学习变的简单)

http://m.blog.csdn.net/blog/yhc13429826359/19977429

1生命周期图

2主要类图调用

上面类图关系中包含两个进程,一个是应用程序进程,另一个是AMS进程,所以会涉及到进程间通信,android进程间通信用的是Binder通信。

2.1客户进程

ØActivityThread

可以看到该类有一个main方法,其实它是android一个应用程序的入口,每启动一个应用进程,都会创建ActivityThread与之对应的实例,是应用程序的UI线程,Android进程启动时会建立消息循环。负责管理应用程序的生命周期,执行系统广播及其ActivityManagerService请求执行的操作。属于客户端对象。

ØApplicationThread&ApplicatinThreadNative

ApplicationThread用来实现ActivityManagerService与ActivityThread之间的交互。在ActivityManagerService需要管理相关Application中的Activity的生命周期时,通过ApplicationThread与ActivityThread通讯,ApplicationThreadNative是ApplicationThread在客户端的实现。

ØApplicationThreadProxy

ApplicationThreadProxy是ApplicationThread在服务器端的代理。负责和服务器端的ApplicatingThreadNative通讯。

AMS就是通过该代理与ActivityThread进行通信的。

ØActivity& Intrumentation

Activity是应用程序真正做事情的类,每一个应用程序只有一个Instrumentation对象,每个Activity内都有一个对该对象的引用。Instrumentation可以理解为应用进程的管家,ActivityThread要创建或暂停某个Activity时,都需要通过Instrumentation。通俗的理解,Instrumentation与ActivityThread的区别,前者像是一个“家庭”里的“管家”,后者是负责创建这个“家庭”,并负责对外打交道,比如接收AMS的通知等。

2.2 AMS进程

这里说的AMS进程,实际指的是System_server进程,System_server进程起来的时候启动AMS服务,AMS实际是ActivityManagerService的缩写。

ØActivityManagerService

管理Activity的生命周期

ØActivityManagerNative

ActivityManagerService在服务器端的实现,客户端的请求调用ActivityManagerProxy后,通过IBinder,最终会在ActivityManagerNative中实现。ActivityManagerNative再通过调用ActivityManagerService的相关功能,以完成客户端请求。

ØActivityManagerProxy

ActivityManagerService的在客户端的代理。负责和服务器端的ActivityManagerNative通讯。

ØActivityStack

Activity在AMS的栈管理,用来记录已经启动的Activity的先后关系,状态信息等。通过ActivityStack决定是否需要启动新的进程。

ØActivityRecord

ActivityStack的管理对象,每个Activity在AMS对应一个ActivityRecord来记录Activity的状态以及其他的管理信息。

ØTaskRecord

AMS抽象出来的一个“任务”的概念,是记录ActivityRecord的栈,一个“Task”包含若干个ActivityRecord。AMS用TaskRecord确保Activity启动和退出的顺序。

ØProcessRecord

一个Apk文件运行时会对应一个进程,ProcessRecord正是记录一个进程中的相关信息。

3startActivity流程

在Android系统中,应用程序是由Activity组成的,因此,应用程序的启动过程实际上就是应用程序中的默认Activity的启动过程。启动Android应用程序中的Activity的两种情景,第一,在android设备屏幕中点击应用程序图标的情景就会引发Android应用程序中的默认Activity的启动,从而把应用程序启动起来,这种启动方式的特点是会启动一个新的进程来加载相应的Activity。第二,应用程序内部启动非默认Activity的过程的源代码,这种非默认Activity一般是在原来的进程和任务中启动的。在Android的Activity管理机制中,当退出Activity的时候,在某些情况下并没有立即把该Activity杀死,而是将其暂时保存起来,当第二次调用startActivity启动该Activity的时候,就不需要再创建该Activity的实例,直接恢复Activity即可。

3.1调用流程图

对用户来讲,启动一个Activity有以下几种方式:

Ø在应用程序中调用startActivity()启动指定的Activity

Ø在Home程序中点击一个应用图标,启动新的Activity

Ø按“Back”键,结束当前Activity,自动启动上一个Activity

Ø长按“Home”键,显示当前列表中,从中选则一个启动

对于AMS内部讲,启动一个Activity有三种方式,如上图中的①②③分支:

①目标Activity的对象已经存在,那么直接resume该Activity

②目标Activity所在的进程不存在,那么需要创建进程,并在新的进程中启动该Activity

③目标Activity所在进程已经存在,那么直接在已存在进程中启动该Activity

3.2在新的进程中启动

以在Home程序中点击一个应用图标,启动MainActivity为例子,介绍如下。

时序图如下图:

框架层理解Activity生命周期

以上时序图包含35步骤调用,下面逐一讲解:

3.2.1(1~4),Launcher中发送startActivity请求

在Android系统中,应用程序是由Launcher启动起来的,其实,Launcher本身也是一个应用程序,其它的应用程序安装后,就会Launcher的界面上出现一个相应的图标,点击这个图标时,Launcher就会对应的应用程序启动起来。

Launcher继承与Activity,Activity类的有个成员变量mInstrumentation是,它的类型是Intrumentation,它用来监控应用程序和系统的交互。

Instrumentation.execStartActivity:

publicActivityResult execStartActivity(

Context who, IBinder contextThread, IBinder token, Activitytarget,

Intent intent, int requestCode, Bundle options) {

IApplicationThread whoThread = (IApplicationThread)contextThread;

……

try {

intent.setAllowFds(false);

intent.migrateExtraStreamToClipData();

int result = ActivityManagerNative.getDefault()

.startActivity(whoThread, intent,

intent.resolveTypeIfNeeded(who.getContentResolver()),

token, target != null ? target.mEmbeddedID : null,

requestCode, 0, null, null, options);

checkStartActivityResult(result, intent);

} catch (RemoteException e) {

}

return null;

}

这里的ActivityManagerNative.getDefault返回ActivityManagerService的远程接口,即ActivityManagerProxy接口。

3.2.2(5-8) AMS接收客户端startActivity请求

客户端通过Binder调用,最终调用到ActivityStack.startActivityLocked:

final intstartActivityLocked(IApplicationThread caller,

Intent intent, String resolvedType, ActivityInfo aInfo, IBinderresultTo,

String resultWho, int requestCode,

int callingPid, int callingUid, int startFlags, Bundleoptions,

boolean componentSpecified, ActivityRecord[] outActivity){

ProcessRecord callerApp = null;

if (caller != null) {

callerApp = mService.getRecordForAppLocked(caller);

if (callerApp != null) {

callingPid = callerApp.pid;

callingUid = callerApp.info.uid;

} else {

……

}

}

….

ActivityRecord sourceRecord = null;

ActivityRecord resultRecord = null;

….

int launchFlags = intent.getFlags();

….

if((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT)!= 0

&& sourceRecord != null){

// Transfer the result target from the source activity to thenew

// one being started, including any failures.

…….

}

……

ActivityRecord r = new ActivityRecord(mService, this, callerApp,callingUid,

intent, resolvedType, aInfo, mService.mConfiguration,

resultRecord, resultWho, requestCode,componentSpecified);

if (outActivity != null) {

outActivity[0] = r;

}

……

err = startActivityUncheckedLocked(r, sourceRecord,

startFlags, true, options);

……

return err;

}

startActivityLock()主要做了一下几件事:

①处理传进来的参数caller,得到调用者的进程信息,并保存在callerApp变量中,这里就是Launcher应用程序的进程信息了。

②处理FLAG_ACTIVITY_FORWARD_RESULT标志。该标志的特殊作用,就是能跨Activity传Result,比如A1->A2,A2带该标志启动A3,那么A3调用setResult,然后finish(),结果将直接返回到A1

③创建一个临时的ActivityRecord对象,该对象只为了后面调用过程中的各种对比,不一定会最终加入到mHistory列表中。

④判断mPendingActivityLaunches列表是否有等待的Activity要启动,如果有先启动等待的Activity

⑤调用startActivityUncheckedLocked()方法。此时要启动的Activity已经通过检验,被人认为是一个正当的启动请求。

3.2.3(9)创建新的Task

调用ActivityStack.startActivityUncheckedLocked()处理Task问题,因为这里我们是新启动一个apk,所以将创建新的Task,newTask=true,并调用ActivityStack.startActivityLoacked():

privatefinal void startActivityLocked(ActivityRecord r, booleannewTask,

boolean doResume, boolean keepCurTransition) {

……

if (!newTask) {

…….

}

}

// Place a new activity at top of stack, so it is next tointeract

// with the user.

if (addPos < 0) {

addPos = NH;

}

……

mHistory.add(addPos, r);

r.putInHistory();

r.frontOfTask = newTask;

……

if (doResume) {

resumeTopActivityLocked(null);

}

}

注意AtivityStack中有两个startActivityLoacked()方法,这里调用的是带四个参数的,即startActivityLocked(ActivityRecord r, booleannewTask,boolean doResume, booleankeepCurTransition),其中,r为将要启动的Activity,newTask=true,doResume=true,在这个方法中,将r放到mHistory的最后面doResume=true,所以调用resumeTopActivityLocked(null)。关于Task的概念比较复杂,这里先不讲解。

3.2.4:(10)运行mHistory中最后一个ActivityRecord

ActivityStack. resumeTopActivityLocked(null)

finalboolean resumeTopActivityLocked(ActivityRecord prev) {

// Find the first activity that is not finishing.

ActivityRecord next = topRunningActivityLocked(null);

if (next == null) {

// There are no more activities! Let"s just startup the

// Launcher...

if (mMainStack) {

return mService.startHomeActivityLocked();

}

}

next.delayedResume = false;

// If the top activity is the resumed one, nothing todo.

if (mResumedActivity == next &&next.state == ActivityState.RESUMED) {

// Make sure we have executed any pending transitions, sincethere

// should be nothing left to do at this point.

mService.mWindowManager.executeAppTransition();

mNoAnimActivities.clear();

return false;

}

// If we are sleeping, and there is no resumed activity, and thetop

// activity is paused, well that is the state we want.

if ((mService.mSleeping || mService.mShuttingDown)

&& mLastPausedActivity == next&& next.state ==ActivityState.PAUSED) {

// Make sure we have executed any pending transitions, sincethere

// should be nothing left to do at this point.

mService.mWindowManager.executeAppTransition();

mNoAnimActivities.clear();

returnfalse;

}

// The activity may be waiting for stop, but that is nolonger

// appropriate for it.

mStoppingActivities.remove(next);

mGoingToSleepActivities.remove(next);

next.sleeping = false;

mWaitingVisibleActivities.remove(next);

……

if (mPausingActivity != null) {

if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" +mPausingActivity);

return false;

}

…..

// We need to start pausing the current activity so the topone

// can be resumed...

if (mResumedActivity != null) {

if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to startpausing");

startPausingLocked(userLeaving, false);

return true;

}

……..

}

调用resumeTopActivityLocked(null)启动真正的Activity。

①调用topRunningActivityLocked()方法取出当前正在运行的ActivityRecord对象

②判断mHistory中是否有记录,如果没有就意味着还没有启动任何的Activity,需要首先调用mService.startHomeActivityLocked()方法启动所谓的“主界面程序”。当然我们这里mHistroy已经有记录了。

③判断正在执行的Activity是否和目标Activity一样,如果一样,则直接返回。

④判断当前系统是否处于休眠涨停,如果是,则返回。这里继续往下执行。

⑤从mStoppingActivities、mWaitingVisibleActivities和mGoingToSleepActivities中删除目标对象,因为接下来将要被启动。

⑥判断当前是否在暂停某个Activity,如果是则还不能运行。这里mPausingActivity=null,所以继续往下执行。

⑦判断当前是否有Activity在运行,如果有则先需要暂停当前的Activity。因为我们是在Lancher中启动mainActivity,所以当前mResumedActivity!=null,所有调用startPausingLocked(userLeaving, false);

3.2.5(11~16)暂停当前运行Activity

①调用ActivityStack.startPausingLocked()暂停当前Activity。

②判断运行当前Activity的进程是否存在。在这里 if (prev.app != null&& prev.app.thread !=null)为真。其中,prev.app为记录启动Lancher进程的ProcessRecord,prev.app.thread为Lancher进程的远程调用接口IApplicationThead,所以可以调用prev.app.thread.schedulePauseActivity,到Lancher进程暂停指定Activity。

③在Lancher进程中消息传递,调用ActivityThread.handlePauseActivity(),最终调用ActivityTHread.performPauseActivity暂停指定Activity。接着通过Binder通信,通知AMS已经完成暂停ActivityManagerNative.getDefault().activityPaused(token).

3.2.6(17~20) AMS处理暂停Activity事情

在Launcher通过Binder进程间通信机制通知AMS,它已经准备就绪进入Paused状态,在ActivityStack.completePauseLocked()中完成暂停:

private final void completePauseLocked(){

ActivityRecord prev = mPausingActivity;

if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);

if (prev != null) {

if (prev.finishing) {

prev = finishCurrentActivityLocked(prev,FINISH_AFTER_VISIBLE);

} else if (prev.app != null) {

……

if (prev.configDestroy) {

destroyActivityLocked(prev, true, false,"pause-config");

} else {

mStoppingActivities.add(prev);

if (mStoppingActivities.size() > 3) {

// If we already have a few activities waiting to stop,

// then give up on things going idle and start clearing

// them out.

if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcingidle");

scheduleIdleLocked();

} else {

checkReadyForSleepLocked();

}

}

} else {

if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping:" + prev);

prev = null;

}

mPausingActivity = null;

}

if (!mService.isSleeping()) {

resumeTopActivityLocked(prev);

} else {

checkReadyForSleepLocked();

}

……

}

①给prev赋值mPausingActivity,即上一个被执行的Activity,即Launcer

②如果prev的finishing为true,说明上一个Activity已经完成,因此需要调用finishCurrentActivityLocked()执行相关操作。一般的流程不会为true,这个条件似乎只有内存回收的时候才会被执行。

③将mPausingActivity变量置为空

④调用resumeTopActivityLocked方法正式启动目标Activity,即MainActivity

3.2.7:(21~23)正式启动目标Activity

调用AcivityStack.resumeTopActivityLocked:

final booleanresumeTopActivityLocked(ActivityRecord prev) {

ActivityRecord next = topRunningActivityLocked(null);

……

if (mResumedActivity != null) {

if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to startpausing");

startPausingLocked(userLeaving, false);

return true;

}

if (next.app != null &&next.app.thread != null) {

……

}

startSpecificActivityLocked(next, true, true);

}

return true;

}

①该方法在3.2.4步骤中调用过,那时是因为mResumedActivity != null,有Activity正在运行,所以去执行了startPausingLocked暂停Laucher去了。这时候,mResumedActivity=null,所以继续往下执行。

②判断讲要启动的Activity的客户进程是否存在,这里next.app != null &&next.app.thread != null为false

③调用ActivityStack.startSpecificActivityLocked

private final voidstartSpecificActivityLocked(ActivityRecord r,

boolean andResume, boolean checkConfig) {

// Is this activity"s application already running?

ProcessRecord app =mService.getProcessRecordLocked(r.processName,

r.info.applicationInfo.uid);

……

if (app != null && app.thread !=null) {

……

realStartActivityLocked(r, app, andResume, checkConfig);

return;

}

mService.startProcessLocked(r.processName, r.info.applicationInfo,true, 0,

"activity", r.intent.getComponent(), false);

}

④客户进程不存在,app!= null && app.thread !=null为false,所以调用mService.startProcessLocked() fork一个新的进程。

3.2.8(24) fork一个新的进程

①AMS通过Socket通信,向Zygote发送一个创建进程请求,Zygote创建新进程。

②创建好进程后,调用ActivityThread.main()。到此,我们到了新了一个进程中,也是程序的入口出。

③调用ActivityThread.attach()开始新的应用程序,接着同过Binder通信通知AMS,新的进程已经创建好了,可以开始新的程序了。

3.2.9(26~28) AMS准备执行目标Activity

目标进程启动后,报告给AMS,自己已经启动完毕可以启动Activity了,这里通过IPC调用AMS的attachApplication方法完成。

ActivityManagerService.attachApplication():

public final voidattachApplication(IApplicationThread thread) {

synchronized (this) {

int callingPid = Binder.getCallingPid();

final long origId = Binder.clearCallingIdentity();

attachApplicationLocked(thread,callingPid);

Binder.restoreCallingIdentity(origId);

}

}

①根据Binder.getCallingPid(),或得客户进程pid,并调用attachApplicationLocked(IApplicationThreadthread,int pid)

②在attachApplicationLocked中,根据pid找到对应的ProcessRecord对象,如果找不到说明改pid客户进程是一个没经过AMS允许的进程。

private final booleanattachApplicationLocked(IApplicationThread thread,

int pid) {

ProcessRecord app;

if (pid != MY_PID && pid>= 0) {

synchronized (mPidsSelfLocked) {

app = mPidsSelfLocked.get(pid);

}

}

if (app == null) {

……

returnfalse;

}

// If this application record is still attached to aprevious

// process, clean it up now.

if (app.thread != null) {

服务热线
电话:175-0840-8227
上班时间:9:00-18:00

关注微信公众号