Android-Activity生命周期

文章参考:文章参考1
文章参考:文章参考2

五大状态

  • Starting
  • Running
  • Stopped
  • Paused
  • Destroyed
    借用一张已经包浆的图
    在这里插入图片描述
    PS:Running和Paused是可视阶段,其余都是不可视

几大函数

在这里插入图片描述

  • onCreate:通过setContentLayout初始化布局
  • onStart:此时activity可见,但没有获得焦点,无法交互,正做动画的初始化
  • onResume:获得焦点,可交互
  • onPause:如弹窗,有activity覆盖当前activity,失去焦点,但可见
  • onStop:activity不可见,系统内存紧张时会回收
  • onDestroy:结束activity

进程优先级

前台进程>可见进程>service进程>后台进程>空进程

前台进程

用户当前在做的事所必须的进程,符合其一则为

  • 进程的activity正在与用户进行交互
  • 进程持有一个service,且此service与正在交互的activity绑定/通过startForeground()在前台运行/正在进行其生命周期回调函数
  • 进程持有一个正在进行onReceive()的BroadcostReceiver

可见进程

不持有任何前台组件,但仍可见

  • 进程持有activity,此activity不在前台,处于onPause
  • 进程持有的service与可见的activtiy进行绑定

服务进程

没有和用户可见的组件绑定,所做的事情也是用户关心的,如后台下载、播放音乐的,除非内存不足,不然不会取消
当进程运行着一个startService开启的的service,且不属于前台和可见进程

后台进程

持有不可见activity,onStop调用,但没有调用onDestroy,系统会为了前三种进程任意杀死后台进程

空进程

不包含任何活跃的应用组件,则被认为是空进程
没有任何运行数据且还在内存空间,容易被杀死

启动流程

此处针对Activity A通过button点击启动位于不同进程的Activity B进行分析
在这里插入图片描述

概念梳理

  • init进程:init是所有linux程序的起点,是Zygote的父进程。解析init.rc孵化出Zygote进程。Android是基于linux系统的,手机开机之后,linux内核进行加载。加载完成之后会启动init进程。init进程会启动ServiceManager,孵化一些守护进程,并解析init.rc孵化Zygote进程
  • Zygote进程:Zygote是所有Java进程的父进程,所有的App进程都是由Zygote进程fork生成的。所有的App进程都是由Zygote进程fork生成的,包括SystemServer进程。Zygote初始化后,会注册一个等待接受消息的socket,OS层会采用socket进行IPC通信。每个应用程序都是运行在各自的Dalvik虚拟机中,应用程序每次运行都要重新初始化和启动虚拟机,这个过程会耗费很长时间。Zygote会把已经运行的虚拟机的代码和内存信息共享,起到一个预加载资源和类的作用,从而缩短启动时间。
  • SystemServer进程:System Server是Zygote孵化的第一个进程。SystemServer负责启动和管理整个Java framework,包含AMS,PMS等服务。
  • Launcher:Zygote进程孵化的第一个App进程是Launcher。
  • 进程:Android系统为每个APP分配至少一个进程
  • IPC:跨进程通信,Android中采用Binder机制。
  • ActivityStack:Activity在AMS的栈管理,用来记录已经启动的Activity的先后关系,状态信息等。通过ActivityStack决定是否需要启动新的进程。
  • ActivitySupervisor:管理 activity 任务栈
  • ActivityThread:ActivityThread 运行在UI线程(主线程),App的真正入口。
  • ApplicationThread:用来实现AMS和ActivityThread之间的交互。
  • ApplicationThreadProxy:ApplicationThread 在服务端的代理。AMS就是通过该代理ActivityThread进行通信的。
  • IActivityManager:继承与IInterface接口,抽象出跨进程通信需要实现的功能
  • AMN:运行在server端(SystemServer进程)。实现了Binder类,具体功能由子类AMS实现。
  • AMS:AMN的子类,负责管理四大组件和进程,包括生命周期和状态切换。AMS因为要和ui交互,所以极其复杂,涉及window。
  • AMP:AMS的client端代理(app进程)。了解Binder知识可以比较容易理解server端的stub和client端的proxy。AMP和AMS通过Binder通信。
  • Instrumentation:仪表盘,负责调用Activity和Application生命周期,负责监控系统与应用之间的交互。测试用到这个类比较多。
  • ActivityStackSupervisor负责所有Activity栈的管理。内部管理了mHomeStack、mFocusedStack和mLastFocusedStack三个Activity栈。
  • mHomeStack管理的是Launcher相关的Activity栈
  • mFocusedStack管理的是当前显示在前台Activity的Activity栈
  • mLastFocusedStack管理的是上一次显示在前台Activity的Activity栈

省流四步

  • A告诉AMS准备启动B
  • AMS处理请求,通知A进行Pause,A处理完后,通知AMS 自己已经完成Pause了
  • B的进程还没启动,AMS首先启动一个新的进程,新进程启动完后通知AMS服务进程启动完毕
  • AMS通知新进程启动B,B启动完毕后通知AMS服务启动完毕

AMS和应用进程间通信涉及进程间通信,与Binder有关

当创建了一个新的应用进程后,系统首先会启动ActivityThread,ActivityThread是应用进程的主线程,ActivityThread创建时会创建一个ApplicationThread对象,ApplicationThread实现了一个Binder服务端

新进程创建完时会通知AMS,同时会将ApplicationThread的代理端交付,因此AMS保存了所有应用进程的ApplicationThread的代理对象,用于给应用进程发送消息

Activity.startActivity

此处button点击函调用了该函数

public void startActivity(Intent intent, @Nullable Bundle options) {if (options != null) {//intent描述B,-1表示不返回结果startActivityForResult(intent, -1, options);……
}

Activity. startActivityForResult

public void startActivityForResult( String who, Intent intent, int requestCode, @Nullable Bundle options) {Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, who,intent, requestCode, options);……
}

应用程序和系统间的交互都集中交给Instrumentation来做,便于监视活动
mMainThread.getApplicationThread()是前面提到的Binder对象,实现了Binder服务端,AMS保留其client用于通信
mToken则是binder代理对象,指向AMS中保存的一个ActivityRecord信息,mToken代表了A,AMS依据其得到A的信息

Instrumentation. execStartActivity

public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {ApplicationThread whoThread = (IApplicationThread) contextThread;try {//intent做进程间传输的准备工作intent.migrateExtraStreamToClipData();intent.prepareToLeaveProcess();//进程间传输,终于调用到AMS服务中int result = ActivityManagerNative.getDefault().startActivity(whoThread, who.getBasePackageName(), intent,intent.resolveTypeIfNeeded(who.getContentResolver()),token, target != null ? target.mEmbeddedID : null,requestCode, 0, null, options);checkStartActivityResult(result, intent);}……
}

通过ActivityManagerNative.getDefault().startActivity()调用AMS的startActivity方法

至此都是在A的进程完成的,需要进入SystemServer中

这里调用了startActivity来启动Activity(最常用的函数),里面调用startActivityForResult,但给出的请求码是-1,即不返回数据
startActivityForResult调用了Instrumentation的execStartActivity,并传入ApplicationThread给AMS作为通信的binder对象,也传入mToken作为指向A的ActivityRecord给AMS

AMS.startActivity

public final int startActivity (IApplicationThread caller, String callingPackage,Intent intent, String resolvedType, IBinder resultTo, 
String resultWho, int requestCode,int startFlags, ProfilerInfo profilerInfo, Bundle options) {return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, options,UserHandle.getCallingUserId());
}

caller就是App1进程的ApplicationThread的binder对象,
IBinder就是指向Activity A的ActivityRecord的Binder对象,前面提到的通信和获取活动信息所需
紧接着这种方法就调用了startActivityAsUser方法

AMS. startActivityAsUser

public final int startActivityAsUser(IApplicationThread caller, String callingPackage,Intent intent,String resolvedType, IBinder resultTo, String resultWho,int requestCode,int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {……return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,profilerInfo, null, null, options, false, userId, null, null);
}

调用了activityStackSupervisor的startActivityMayWait方法
ActivityStackSupervisor是Activity调度的核心类
Activity的调度相关的工作都是在ActivityStackSuperVisor中处理
主要管理Task和Stack.它是在AMS启动的时候创建的。

startActivityMayWait

final int startActivityMayWait(IApplicationThread caller, int callingUid,String callingPackage, Intent intent, String resolvedType,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,Bundle options, boolean ignoreTargetSecurity, int userId,
IActivityContainer iContainer, TaskRecord inTask) {……//PMS服务依据intent查询要启动的Activity B的信息,保存到ActivityInfo中intent = new Intent(intent);ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);//决定当前活动的stackActivityContainer container = (ActivityContainer)iContainer;final ActivityStack stack;if (container == null || container.mStack.isOnHomeDisplay()) {stack = mFocusedStack;} else {stack = container.mStack;}……//将PMS中查询到的Activity B的信息当做參数int res = startActivityLocked(caller, intent, resolvedType, aInfo,voiceSession, voiceInteractor, resultTo, resultWho,requestCode, callingPid, callingUid, callingPackage,realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,componentSpecified, null, container, inTask);……
}

resolveActivity调用PMS服务依据Intent信息查询B的具体信息
查询是否有对应的ActivityStack,若传递过来的container为空,则指定Stack为当前获得焦点的ActivityStack,即mFocusedStack

ActivityStack分为几种

  • Home Stack 为 Launcher所在的Stack,一些系统界面也在此Stack执行,SystemUI等
  • FullScreen Stack 全屏的Activity所在的Stack,最常用
  • Freeform模式的Activity所在Stack,即可以自由缩放,自由移动
  • Docked Stack,分屏模式
  • Pinned Stack 画中画

startActivityLocked

final int startActivityLocked(IApplicationThread caller,Intent intent, String resolvedType, ActivityInfo aInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,IBinder resultTo, String resultWho, int requestCode,int callingPid, int callingUid, String callingPackage,int realCallingPid, int realCallingUid, int startFlags, Bundle options,
boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,ActivityContainer container, TaskRecord inTask) {//callerApp 代表调用方的应用进程。即App1的应用进程ProcessRecord callerApp = null;if (caller != null) {//依据caller找到AMS中保存的App1的processRecord对象callerApp = mService.getRecordForAppLocked(caller);if (callerApp != null) {//得到App1应用进程的pid和应用的uidcallingPid = callerApp.pid;callingUid = callerApp.info.uid;}……}……//即调用者的Activity组件ActivityRecord sourceRecord = null;//返回结果的Activity组件ActivityRecord resultRecord = null;if (resultTo != null) {//依据resultTo Binder对象得到其指向的ActivityRecord,即Activity A的ActivityRecord信息sourceRecord = isInAnyStackLocked(resultTo);//普通情况下请求的Activity和要接收返回结果的Activity是同一个if (sourceRecord != null) {if (requestCode >= 0 && !sourceRecord.finishing) {resultRecord = sourceRecord;}}}final int launchFlags = intent.getFlags();……//依据准备的信息,创建一个即将启动的ActivityRecord对象。即Activity BActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,requestCode, componentSpecified, voiceSession != null, this, container, options);……//将刚创建的目标Activity的ActivityRecord作为參数,继续调用startActivityUncheckedLocked方法来启动err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,startFlags, true, options, inTask);……return err;
}

依据传入的A的binder对象caller获得A的ActivityRecord信息,获取调用程序的pid和uid
加上ainfo创建一个ActivityRecord对象r,代表B
至此sourceRecord获取了A的组件消息,r获取了B的信息
最终调用startActivityUncheckedLocked启动B

startActivityUncheckedLocked

final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
boolean doResume, Bundle options, TaskRecord inTask) {//依据flag获取对应的启动模式。我们代码中没有设置启动模式,所以默认应该是标准模式。这三个变量都应该是false		final boolean launchSingleTop = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP;final boolean launchSingleInstance = r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE;final boolean launchSingleTask = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK;……//即将要启动activity的 taskActivityStack targetStack;……//是否新建一个Taskboolean newTask = false;……//获取Activity A的Task,然后赋值给B,即两个Activity位于同一个Task中else if (sourceRecord != null) {//获取Activity A所在的Taskfinal TaskRecord sourceTask = sourceRecord.task;//将A所在的ActivityStack作为B启动的StacktargetStack = sourceTask.stack;targetStack.moveToFront("sourceStackToFront");//获取ActivityStack中的 top Task是不是和当前的Task一致,假设不一致则将当前的Task移动到ActivityStack的顶端final TaskRecord topTask = targetStack.topTask();if (topTask != sourceTask) {targetStack.moveTaskToFrontLocked(sourceTask, noAnimation, options,r.appTimeTracker, "sourceTaskToFront");}……//将当前Activity Stack mLastPausedActivity设置为nulltargetStack.mLastPausedActivity = null;//调用startActivityLocked方法targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
}

这里处理了Activity四种启动模式,根据Intent中的flag标志来决定不同的启动模式和Activity在Task中的位置
此处的启动模式是默认的,因此A和B同放在一个Task里面

每个Activity都位于一个Task中,一个Task能够包括多个Activity,同一个Activity也可由多个实例

Task管理在于近期任务列表和Back栈,AMS和WMS内部有一个容器Stack,android多窗体管理建立在Stack上,一个Stack中多个Task,一个Task包括多个Activity

最后调用ActivityTask的startActivityLocked启动

ActivityStack . startActivityLocked

final void startActivityLocked(ActivityRecord r, boolean newTask,boolean doResume, boolean keepCurTransition, Bundle options) {//获取要启动的Task对象TaskRecord rTask = r.task;final int taskId = rTask.taskId;TaskRecord task = null;if (!newTask) {//遍历AMS中全部的Task,找到目标task,然后将即将要启动的Activity增加到Task的栈顶boolean startIt = true;for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {task = mTaskHistory.get(taskNdx);if (task.getTopActivity() == null) {// All activities in task are finishing.continue;}if (task == r.task) {if (!startIt) {task.addActivityToTop(r);r.putInHistory();……//传入的resume位true。然后调用resumeTopActivitiesLocked方法继续启动Activity			if (doResume) {mStackSupervisor.resumeTopActivitiesLocked(this, r, options);}

遍历全部Task,找到目标Task,将即将要启动的Activity的ActivityRecord增加到栈顶

ActivityStackSuperVisor. resumeTopActivitiesLocked

boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target, Bundle targetOptions) {//假设目标task是frontStack调用resumeTopActivityLockedif (isFrontStack(targetStack)) {result = targetStack.resumeTopActivityLocked(target, targetOptions);}//然后遍历找到时frontStack的task运行resumeTopActivityLockedfor (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {……}if (isFrontStack(stack)) {stack.resumeTopActivityLocked(null);}……

确认目标task是否为frontStack,若是则直接执行resumeTopActivityLocked,不是则遍历,找到对应的frontStack执行resumeTopActivityLocked

ActivityStack.resumeTopActivityLocked

直接有调用了resumeTopActivityInnerLocked方法

ActivityStack. resumeTopActivityInnerLocked

ActivityStack. resumeTopActivityInnerLocked private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {……//找到栈顶第一个不是处于finishing状态的ActicityRecordfinal ActivityRecord next = topRunningActivityLocked(null);……//调用startPausingLocked方法来暂停上一个Activityif (mResumedActivity != null) {if (DEBUG_STATES) Slog.d(TAG_STATES,"resumeTopActivityLocked: Pausing " + mResumedActivity);pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
}

topRunningActivityLocked找到当前栈顶不是处于fininshiing状态的第一个ActivityRecord
将B的ActivityRecord添加到当前Task的栈顶,即next
startPausingLocked暂停上一个Activity
ActivityStack有三个成员变量:mResumedActivity、mLastResumedActivity、mLastPausedActivity

  • mResumedActivity:栈中激活状态的activity
  • mLastResumedActivity:栈中上一次被暂停的activity
  • mLastPausedActivity:栈中正在被暂停的activity
    mResumedActivity != null表示A不为空,暂停A

总结 startActivity到Pause

Activity的startActivity方法启动目标Activity

Instrumentation的方法execStartActivity,方便Instrumentation对交互进行监測

以上部分是在App1的进程中运行。之后会通过进程间通信调用到AMS服务中调用AMS的startActivity方法。

此时进入SystemServer进程。

然后由AMS中管理Acticity核心调度的类ActivityStackSupervisor的方法startActivityMayWait来处理。该方法中主要是依据Intent从PMS中查询目标Activity的信息

ActivityStackSuperVisor的startActivityLocked方法主要是在AMS中找调用进程的processRecord信息,调用Activity的ActivityRecord信息。目标Activity还没有启动,所以须要先创建一个目标Activity的ActivityRecord信息。

ActivityStackSuperVisor的StartActivityUncheckedLocked方法主要来处理启动模式相关的逻辑,依据不同的启动模式,找到对应的对的ActivityStack,然后又对应的ActivityStack进行处理

ActivityStack将目标Activity增加到相应的Task栈顶

调用ActivityStackSuperVisor的resumeTopActivityLocked方法找到处于前台的Task。然后调用它的resumeTopActivityLocked方法激活目标Activity.

当前的Task的栈開始Pasuing调用的Activity

以上几个步骤完成AMS对调用Activity及目标Activity的信息收集处理
拿到启动进程的binder对象和A的activityRecord给AMS
通过ActivityStackSuperVisor拿到启动进程的信息
根据Intent拿到目标Activity的信息
依据启动模式来决定将目标Activity方法那个栈中。然后将目标栈当前处于激活状态的Activity Pause掉给目标Activity腾地方。

Activity Resume - Pause

ActivityStack.startPausingLocked

final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,boolean dontWait) {//mResumeActivity代表当前激活的Activity。即Activity AActivityRecord prev = mResumedActivity;……//当前处于激活状态mResumedActivity 的设置为nullmResumedActivity = null;//即将要处于pasuing状态的Activity 就是Activity AmPausingActivity = prev;mLastPausedActivity = prev;……//将Activity A的状态设置为PAUSINGprev.state = ActivityState.PAUSING;//找到当前的栈顶的topActivity就是 Activity Bfinal ActivityRecord next = mStackSupervisor.topRunningActivityLocked();//调用进程不为null,且调用进程的ApplicationThread不为nullif (prev.app != null && prev.app.thread != null) {try {……//通过调用进程的ApplicationThread通知调用进程schedulePauseActivity方法prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,userLeaving, prev.configChangeFlags, dontWait);}

从mResumeActivity拿到A的ActivityRecord,赋值prev
并将其和B设为pause状态,因为B暂时未启动,未激活
prev.app代表A的ProcessRecord,prev.app.thread则为A所在进程的ApplicationThread
通过ApplicationThread可以得到进程的Binder client,使得AMS能够向应用进程发送消息
最终通过调用A的schedulePauseActivity,完成Pause

ApplicationThread. schedulePauseActivity

public final void schedulePauseActivity(IBinder token, boolean finished,boolean userLeaving, int configChanges, boolean dontReport) {sendMessage(finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,token,(userLeaving ?1 : 0) | (dontReport ? 2 : 0),configChanges);
}

应用进程的ApplicationThread是ActivityThread的一个内部类,token是一个Binder类型的对象,指向了AMS中与A的ActivityRecord,根据finish决定是暂停结束还是暂停
这里发送了PAUSE_ACTIVITY的message给handler

……
handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,(msg.arg1&2) != 0);

ActivityThread.handPauseActivity

private void handlePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges, boolean dontReport) {
ActivityClientRecord r = mActivities.get(token);
if (r != null) {//调用Activity A的onPause方法performPauseActivity(token, finished, r.isPreHoneycomb());//等待pause状态的数据写入完毕.if (r.isPreHoneycomb()) {QueuedWork.waitToFinish();}……try {//进程间通信。调用AMS的ActivityPause方法ActivityManagerNative.getDefault().activityPaused(token);} catch (RemoteException ex) {}

ActivityThread中的mActivites集合中保存了当前进程的所有Activity,每个Activity都用一个ActivityClientRecord表示,集合中以binder为key保存
AMS中的全部Activity也是在一个集合中存储,以ActivityRecord来表示,key值也是Binder对象

此处由token获取获取ActivityClientRecord
performPauseActivity调用了A的onSaveInstance,然后调用了onPause
因为onSaveInstance需要存储当前Activity的信息,进行I/O操作,所以需要QueuedWork.waitToFinish来等待存储完成
最后调用activityPaused,进入SystemServer进程

AMS.activityPaused

public final void activityPaused(IBinder token) {//获取Activity 所在的ActivityStackActivityStack stack = ActivityRecord.getStackLocked(token);if (stack != null) {//调用目标ActivityStack的activityPauseLocked方法stack.activityPausedLocked(token, false);}}

Token代表的是Activity A ,此处依据token找到Activity A所在的ActivityStack,然后由目标Stack来处理activityPause逻辑

ActivityStack.activityPauseLocked

final void activityPausedLocked(IBinder token, boolean timeout) {//依据token获取Activity A的ActivityRecord对象final ActivityRecord r = isInStackLocked(token);if (r != null) {//移除pause超时消息mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);if (mPausingActivity == r) {//调用completePauseLocked方法继续运行pause逻辑completePauseLocked(true);
}
……

当运行完pause逻辑的ActivityRecord和我们运行pause逻辑前的activityRecord一样的时候,即是同一个Activity。
就能够调用completePauseLocked方法来完毕Activity A Pause最后的逻辑了。

ActivityStack. completePauseLocked

if (resumeNext) {final ActivityStack topStack = mStackSupervisor.getFocusedStack();if (!mService.isSleepingOrShuttingDown()) {mStackSupervisor.resumeTopActivitiesLocked(topStack, prev, null);}……
}

resumeNext就是completePauseLocked传进来的參数,为true。
调用mStackSupervisor的getFocusedStack()方法来获取正在处理的ActivityStack. mService.isSleepingOrShuttingDown。推断AMS服务是否处于正常激活状态
然后调用mStackSupervisor的resumeTopActivitiesLocked继续处理。

ActivityStackSuperVisor.resumeTopActivitiesLocked

假设当前的ActivityStack是frontStack。
直接调用ActivityStack的resumeTopActivityLocked。
ActivityStack的resumeTopActivityLocked方法则直接有调用了ActivityStack的resumeTopActivityInnerLocked方法。

ActivityStack. resumeTopActivityInnerLocked

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {……//找到栈顶的Activity,此时栈顶的acitvity就是即将要启动的Activity Bfinal ActivityRecord next = topRunningActivityLocked(null);……//我们知道,在前面Activity A变为pause状态的时候。我们就把mResumeActivity 置为了Nullif (mResumedActivity != null) {if (DEBUG_STATES) Slog.d(TAG_STATES,"resumeTopActivityLocked: Pausing " + mResumedActivity);pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);}……//即将要启动的Activity处于一个新的进程,眼下还没有启动if (next.app != null && next.app.thread != null) {……}else{……//来启动目标ActivitymStackSupervisor.startSpecificActivityLocked(next, true, true);}

推断mResumeActivity不为空,说明当前有一个处于正在激活状态的Activity,须要先将原先的Activity变为pause状态。
当Activity A变为Pause状态后。再次走到这种方法来激活目标Activity,此时mResumeActivity已经为空,所以不须要再运行pause的逻辑。
然后推断目标Activity next的进程app和ApplicationThread是否为空,由于Activity A 所在的进程还没有创建,所以两个都为空,直接运行mStackSupervisor的startSpecificActivityLocked来启动新的Activity。

此阶段由ActivityStack.startPausingLocked开始,将A进行Pause,调用onRestoreinstance保存信息等,修改当前的ActivityStack的激活activity等信息,然后定位B的ActivityStack,暂停栈顶Activity,并启动新进程

启动新进程

ActivityStackSuperVisor. startSpecificActivityLocked

void startSpecificActivityLocked(ActivityRecord r,boolean andResume, boolean checkConfig) {//获取目标Activity的进程ProcessRecordProcessRecord app = mService.getProcessRecordLocked(r.processName,r.info.applicationInfo.uid, true);……//因为目标Activity所在进程还没有创建,所以为空if (app != null && app.thread != null) {……}//mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,"activity", r.intent.getComponent(), false, false, true);
}

该方法比較简单,依据目标Activity的ProcessName来查找相应的ProcessRecord.
依据processRecord中的进程app和ApplicationThread来推断
假设这两个变量不为空,说明目标Activity的进程和执行环境已经具备
直接启动Activity就能够,我们知道眼下目标Activity的进程还没有启动,所以须要调用AMS先启动一个目标Activity的进程

AMS. startProcessLocked

final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,……) {long startTime = SystemClock.elapsedRealtime();ProcessRecord app;if (!isolated) {app = getProcessRecordLocked(processName, info.uid, keepIfLarge);String hostingNameStr = hostingName != null?hostingName.flattenToShortString()null……startProcessLocked(app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);……}……
}

获得ProcessRecord,调用startProcessLocked

private final void startProcessLocked(ProcessRecord app, String hostingType,String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {int uid = app.uid;int[] gids = null;……//從PMS服务中查找目标应用相应的权限组final IPackageManager pm = AppGlobals.getPackageManager();permGids = pm.getPackageGids(app.info.packageName, app.userId);……gids = new int[permGids.length + 2];System.arraycopy(permGids, 0, gids, 2, permGids.length);……app.gids = gids;……if (entryPoint == null) entryPoint = "android.app.ActivityThread";//调用Process的静态方法启动一个新的进程 Process.ProcessStartResult startResult = Process.start(entryPoint,app.processName, uid, uid, gids, debugFlags, mountExternal,app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,app.info.dataDir, entryPointArgs);

这种方法做的主要工作就是调用Process的静态方法启动一个新的进程。
启动新的进程的过程大概是
Zygote进程会fork一个新的子进程出来,子进程创建完毕之后
classLoader载入ActivityThread类并创建一个ActivityThread实例
反射调用ActivityThread的main方法
这样ActivityThread主线程就在新的进程中启动起来了。
接着看ActivityThread的main方法,此时已经在新的进程中运行了。

ActivityThread.main

public static void main(String[] args) {Looper.prepareMainLooper();ActivityThread thread = new ActivityThread();thread.attach(false);if (sMainThreadHandler == null) {sMainThreadHandler = thread.getHandler();} Looper.loop();

这种方法主要工作就是调用Looper.prepareMainLooper创建一个消息循环队列
然后调用Looper.loop进入消息循环,当前线程进入消息循环中
使当前线程成为新进程的主线程,然后创建一个ActivityThread对象。调用Attach方法。

ActivityThread.attach

final ApplicationThread mAppThread = new ApplicationThread();
private void attach(boolean system) {sCurrentActivityThread = this;mSystemThread = system;if (!system) {……final IActivityManager mgr = ActivityManagerNative.getDefault();try {mgr.attachApplication(mAppThread);} catch (RemoteException ex) {// Ignore}……} else {}

初始系统进程的执行环境的时传入的參数system为true,表示是系统进程
而这次是普通的应用进程,所以參数system为false
ActivityManagerNative.getDefault()方法获取AMS的代理
调用attachApplication方法发送一个进程间通信的请求,将创建的ApplicationThread对象传递给AMS服务
ApplicationThread是一个ActivityThread本地binder对象,Binder的服务端在ActivityThread中,将Binder对象传递给AMS服务。则AMS服务中保存它的代理,AMS就获得了与新进程通信的方式。
此前的代码运行在新建的进程中。即应用App2所在的进程,然后通过进程间通信

AMS.attachApplication

      ApplicationInfo appInfo = app.instrumentationInfo != null? app.instrumentationInfo : app.info;		//进程间调用:调用新进程的bindApplication方法thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,isRestrictedBackupMode || !normalMode, app.persistent,new Configuration(mConfiguration), app.compat,getCommonServicesLocked(app.isolated),mCoreSettingsObserver.getCoreSettingsLocked());……if (normalMode) {try {//调用ActivityStackSupervisor的方法来启动新的Activityif (mStackSupervisor.attachApplicationLocked(app)) {didSomething = true;}}……}

依据进程ID,查询相应进程的ProcessRecord,这个ProcessRecord是新进程的对象,指向新进程
从PMS中查询与新进程相关的ContentProvider的信息
这里的thread是新进程的ApplicationThread的binder,调用新进程的handlebindApplication来初始化执行环境,包含新进程Application的初始化、Instrumentation的初始化和安装相关的ContentProvider
最后调用ActivityStackSupervisor执行attachApplication

ActivityStackSuperVisor. attachApplicationLocked

boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {final String processName = app.processName;//遍历全部的stack,找到处于前台的ActivityStackfor (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {ArrayList stacks = mActivityDisplays.valueAt(displayNdx).mStacks;for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {final ActivityStack stack = stacks.get(stackNdx);if (!isFrontStack(stack)) {continue;}//找到处于栈顶的ActivityRecordActivityRecord hr = stack.topRunningActivityLocked(null);if (hr != null) {if (hr.app == null && app.uid == hr.info.applicationInfo.uid&& processName.equals(hr.processName)) {try {//调用realstartActivityLocked方法来启动目标Activityif (realStartActivityLocked(hr, app, true, true)) {didSomething = true;}} catch (RemoteException e) {……}
}

遍历并找到目标stack,然后拿到这个ActivityStack栈顶的ActivityRecord,这就是目标Activity
之前放到栈顶的。得到要启动的Activity信息之后启动新的Activity

ActivityStackSuperVisor. realStartActivityLocked

final boolean realStartActivityLocked(ActivityRecord r,ProcessRecord app, boolean andResume, boolean checkConfig)throws RemoteException {……//将新进程的信息保存到ActivityRecord的app变量中r.app = app;//获取目标Taskfinal TaskRecord task = r.task;//找到Task对用的Stackfinal ActivityStack stack = task.stack;//跨进程调用,通知目标进程来启动Activityapp.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
}

将ActivityRecord的app对象指向了新的进程。这样ActivityRecord就和新的进程关联了起来。
然后通过目标进程ApplicationThread代理Binder对象发起进程间通信请求,调用目标进程的scheduleLaunchActivity方法来启动新的Activity

ApplicationThread. scheduleLaunchActivity

 public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,ActivityInfo info, Configuration curConfig,…… ProfilerInfo profilerInfo) {updateProcessState(procState, false);//依据进程间传递的消息,初始化ActivityClientRecordActivityClientRecord r = new ActivityClientRecord();r.token = token;r.ident = ident;……//发送消息,终于有Handler来处理sendMessage(H.LAUNCH_ACTIVITY, r);}

调用到ActivityThread内部的ApplicationThread中
该ApplicationThread实现了ApplicationThreadNative,这样就实现了进程间通信的Binder服务端
发送消息,由Handler的HandMessage来处理
在handleMessage中又调用了ActivityThread的handleLaunchActivity来处理

ActivityThread.handleLaunchActivity

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {//调用performLaunchActivity方法来启动ActivityActivity a = performLaunchActivity(r, customIntent);//Activity启动完毕后。调用handlResumeActivity来使Activity进入resume激活状态if (a != null) {r.createdConfig = new Configuration(mConfiguration);Bundle oldState = r.state;handleResumeActivity(r.token, false, r.isForward,!r.activity.mFinished && !r.startsNotResumed);}
}

首先调用performLaunchActivity来创建一个Activity对象,并调用Activity的onCreate方法完毕Activity启动
随后调用handleResumeActivity方法。激活Activity,时Activity计入resume状态

ActivityThread.performLaunchActivity

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {ActivityInfo aInfo = r.activityInfo;//获取Activity的packageInfo信息if (r.packageInfo == null) {r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,Context.CONTEXT_INCLUDE_CODE);
}//获取Activity的Component信息ComponentName component = r.intent.getComponent();if (component == null) {component = r.intent.resolveActivity(mInitialApplication.getPackageManager());r.intent.setComponent(component);
}if (r.activityInfo.targetActivity != null) {component = new ComponentName(r.activityInfo.packageName,r.activityInfo.targetActivity);
}//调用Instrumentation类来创建一个依据Activity的信息Activity对象Activity activity = null;java.lang.ClassLoader cl = r.packageInfo.getClassLoader();activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);//创建完毕后,调用Activity的attach方法来初始化Activityif (activity != null) {Context appContext = createBaseContextForActivity(r, activity);CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());Configuration config = new Configuration(mCompatConfiguration);if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "+ r.activityInfo.name + " with config " + config);activity.attach(appContext, this, getInstrumentation(), r.token,r.ident, app, r.intent, r.activityInfo, title, r.parent,r.embeddedID, r.lastNonConfigurationInstances, config,r.referrer, r.voiceInteractor);……//调用Activity的onCreate方法mInstrumentation.callActivityOnCreate(activity, r.state);……//运行Activity的onStart方法if (!r.activity.mFinished) {activity.performStart();r.stopped = false;}……//调用Activity的onRestoreInstancestate方法if (r.state != null) {mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);……//调用Activity的onPostCreate方法mInstrumentation.callActivityOnPostCreate(activity, r.state);……//把创建的相应的ActivityClientRecord以binder为键值,保存到mActivities中mActivities.put(r.token, r);

在新的进程中,依据AMS传递过来的信息创建了一个ActivityClientRecord对象。该对象和AMS服务中的一个ActivityRecord相应。

在这种方法中。依据目标Activity B的ActivityClientRecord,调用Instrumentation类来创建一个Acitivity,创建过程就是ClassLoader载入相应的Activity类,用反射方法创建一个对象。

创建完新的Activity对象后,即Activity B的对象,然后调用它的onCreate方法,这样Activity B的onCreate对象就会被调用,以便载入自定义的用户界面,以及其它的初始化方法。

onCreate方法调用完毕之后。
然后依次调用ActivityonStart,onRestoreInstanceState,onPostCreate方法等,这个就是Activity生命周期运行的逻辑。

创建新进程的总结:
通过Zygote创建新进程,在其main方法中创建消息队列和application。
创建Application传给AMS,查找目标Activity所在的stack,拿到位于栈顶的ActivtiyRecord,对新进程和ActivityRecord进行关联,通过发送消息调用ActivityThread调用handleLaunchActivity来调用performLaunchActivity完成activity的onCreate和activity的onResume

到此为止。ActivityB就启动完毕了,它启动起来之后,意味着ActivityB所在的应用程序也就启动起来了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/18846.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java 八股文-集合框架篇

Java 集合框架 一、常见集合 1.说说有哪些常见集合? 集合相关类和接口都在java.util中,主要分为3种:List(列表)、Map(映射)、Set(集)。 其中Collection是集合List、Set的父接口&#xff0c…

python爬虫入门篇

接下来的一些时间会分享一些爬虫相关的代码和知识 有人会问爬虫怎么舔女神? 我只能说浅了 看完伟大的Technical Licking Dog 的文章你将会对舔狗的认知得到一个升华! 目录 接下来的一些时间会分享一些爬虫相关的代码和知识 正文 爬虫的运行原理&…

程序人生 - 为什么表情包越转发越模糊,还会变绿?

当代人聊天离不开什么? 表情包!!! 没有表情包,怎么表达我的感情?(当然,我对你基本没什么感情~只是想秀一下沙雕表情包!)在过去的日子里,江湖上流传…

⚡【C语言趣味教程】(1) 深入浅出 HelloWorld | 通过 HelloWorld 展开教学 | 头文件详解 | main 函数详解

🔗 《C语言趣味教程》👈 猛戳订阅!!! ​—— 热门专栏《维生素C语言》的重制版 —— 💭 写在前面:这是一套 C 语言趣味教学专栏,目前正在火热连载中,欢迎猛戳订阅&#x…

正确保护Macbook

MacBook该如何正确保护呢?不是各种键盘膜、保护壳通通用上就是最好的,那么该如何正确做呢?下面是macw小编带来的详细指导,快来学习! 在接下来的文章中,笔者将展示哪些配件是可取的,哪些配件是坚…

从做产品的角度分析吕布为什么非死不可?

这是一篇小品文,作者是“产品家实战营3期”学员…… 马中赤兔,人中吕布,本意虽褒,但个人觉得将人与牲口类比,其段位貌似也没高到哪里,:) 不过说起三国里的武将武力排名,吕…

中国撸串指北:13万家烧烤店的吃货最爱

戳蓝字“CSDN云计算”关注我们哦! 数据分析:还是更爱火锅的朱小五 内容撰写:最爱干豆腐卷的王小九 来源|凹凸数读 对美食最大的肯定无疑就是那操着不同口音说出的“好吃!”二字。 ——《人生一串》豆瓣短评 以美食慰藉夜归人&…

Github上这几个沙雕项目,够我玩三天!

点击上方“码农突围”,马上关注 这里是码农充电第一站,回复“666”,获取一份专属大礼包 真爱,请设置“星标”或点个“在看” 开源最前线(ID:OpenSourceTop) 猿妹综合整理 今天,猿妹再…

几个有趣的Github项目,够你玩一阵了...

点击上方“后端技术精选”,选择“置顶公众号” 技术文章第一时间送达! 来源:开源最前线 今天,给大家整理一份有意思的沙雕项目,顺带分享了我的试用成果,说实话,这些项目够你玩三天了。 亲戚关系…

包浆网图分分钟变高清,伪影去除、细节恢复更胜前辈AI,下载可玩|腾讯ARC实验室出品...

丰色 发自 凹非寺量子位 报道 | 公众号 QbitAI 下面来欣赏一些高糊图片“整个世界都清晰了”的魔法时刻: 无论是动漫还是真实图像,是不是都清晰还原了? 以上就是由腾讯ARC实验室最新发表的图像超分辨率模型完成的。 与前人工作相比&#xff0…

爬虫入门实践 | 利用python爬取彩票中奖信息

系统环境:mac python版本:3.6.2(anaconda) 库:requests、BeautifulSoup 爬取一些简单的静态网站,一般采取的策略为:选中目标,也就是需要爬取的网站url;观察结构,查看网页结构&…

全网超详细的下载与安装VMware虚拟机以及为什么要安装VMware虚拟机

文章目录 1. 文章引言2. 下载VMware3. 安装VMware 1. 文章引言 我们使用最多的系统是windows系统,因为,国内电脑厂商的操作系统(os)基本是windows系统,比如华为、联想、华硕等电脑。 但线上的服务器大多是Linux系统,而我们经常使…

图灵奖得主LeCun:ChatGPT局限巨大,自回归模型寿命不超5年

作者 | 新智元 编辑 | 新智元 点击下方卡片,关注“自动驾驶之心”公众号 ADAS巨卷干货,即可获取 【导读】图灵奖得主Yann LeCun畅谈AI:未来是开源。 今年上半年,可谓是AI届最波澜壮阔的半年。 在急速发展的各类GPT甚至AGI的雏形背…

LeCun畅谈:ChatGPT局限巨大,自回归模型寿命不超5年

点击下方卡片,关注“CVer”公众号 AI/CV重磅干货,第一时间送达 点击进入—>【计算机视觉】微信技术交流群 转载自:新智元 | 编辑:拉燕 【导读】图灵奖得主Yann LeCun畅谈AI:未来是开源。 今年上半年,可谓…

ChatGPT正在改变一切但仍然有其局限性

人工智能聊天机器人已经被证明非常有能力完成技术任务,例如编写和编码。但它还不能做所有的事情。 自11月下旬发布以来,ChatGPT已经席卷全球。这款聊天机器人的高级人工智能能力允许它完全独立完成任务,如撰写论文、电子邮件和诗歌、编写和调…

从集异壁理解ChatGPT的成功与局限

终其一生,人类都在探寻认知这个世界的方式。 音乐、绘画和人工智能是三个看似无关的领域,但是它们都是人类这次伟大尝试的绚烂明珠。在这三个领域,追根溯源,底层的结构,都简洁且美丽。 图片由Midjourney生成&#xff0…

GPT虚拟直播Demo系列(二)|无人直播间实现虚拟人回复粉丝

摘要 虚拟人和数字人是人工智能技术在现实生活中的具体应用,它们可以为人们的生活和工作带来便利和创新。在直播间场景里,虚拟人和数字人可用于直播主播、智能客服、营销推广等。接入GPT的虚拟人像是加了超强buff,具备更强大的自然语言处理能…

今晚 12:30 RLHF: From Zero to ChatGPT 直播活动

本次演讲,我们将介绍一种称之为从人类反馈中强化学习 (RLHF, Reinforcement Learning from Human Feedback) 的基础知识,以及如何使用 RLHF 驱动实现 ChatGPT 这样的工具。我们将为大家介绍相关联的机器学习模型,涵盖自然语言处理 (NLP) 和强…

2-24财财的财经早报!

早评0224:震荡依旧 【市场判断】 外围方面,美股三大指数收涨,道指涨0.33%,纳指涨0.72%,标普涨0.53%。消息面上,美联储官员在会议纪要中重申了其强硬的立场——与会者都同意在通胀得到实质控制之前继续加息步伐。芝商所…

一个90后关于ZG足球的思考【卡塔尔世界杯】

前言 一个月的时间过得还是非常快的,卡塔尔世界杯马上也要迎来半决赛和决赛。自己一直想动手写写自己关于足球的思考,特别是ZG足球,说得再准确一点,就是ZG男足。 正文 第一次认识足球运动 作为一名90后,自己开始认…