当前位置:龙泉人才网 - 人才百科 -

青峰科技(Android)

  • 人才百科
  • 2023-12-20 22:00
  • 龙泉小编

在开始正文之前,首先要明白冷启动和热启动.所谓冷启动就是启动该应用时,后台没有该应用的进程,此时系统会创建一个进程分配给它(AMS通过Socket和Zygote通信,Zygote通过forkAndSpecialize()方法向Linux内核申请新进程),之后会创建和初始化Application,然后通过反射执行ActivityThread中的main方法.而热启动则是,当启动应用的时候,后台已经存在该应用的进程,比如按home键返回主界面再打开该应用,此时会从已有的进程中来启动应用,这种方式下,不会重新走Application这一步.

那今天我们主要分析的是应用冷启动的过程.在分析过程中,我发现从Android 2.3到Android 7.0的启动流程总体变化不大,所以,无论你目前是用何版本,下文多是通用的.另外,在本文中,我省略掉了有关Binder这一部分,以便大部分人都能顺利阅读.

从Launcher点击开始

Launcher就是我们所说的桌面,它本质也是一个apk,当我们点击桌面上的图标时,会调用Activity的startActivity(),最终调用startActivityForResult():

public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) { if (mParent == null) {

startActivityForResult将创建过程委托给Instrumenttation的execStartActivity():

public ActivityResult execStartActivity(

在该方法签名中,我们看到第二个参数contextThread是IBinder类型,继续往下看,发现contextThread实则是IApplicationThread的实现类.简单来看IApplicationThread的定义:

public interface IApplicationThread extends IInterface { void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges, boolean dontReport) throws RemoteException; void scheduleStopActivity(IBinder token, boolean showWindow, int configChanges) throws RemoteException; void scheduleWindowVisibility(IBinder token, boolean showWindow) throws RemoteException; void scheduleSleeping(IBinder token, boolean sleeping) throws RemoteException; void scheduleResumeActivity(IBinder token, int procState, boolean isForward, Bundle resumeArgs)

通过大体的阅读IApplicationThread中代码,我们隐约有些熟悉,比如schedulePauseActivity方法应该就是负责Activity中Pause()执行的,scheduleLaunchActivity()应该是负责Activity创建的,scheduleBindService()负责Service绑定的,到现在,我们心里应该会想到IApplicationThread的真正实现类ApplicationThread(位于ActivityThread.java中)就是负责Activity,Service等的创建或其他操作,先来简单的看起其类关系图:

我们继续看Instrumentation的execStartActivity()方法:

int result = ActivityManagerNative.getDefault().startActivity(whoThread, who.getBasePackageName(), intent,intent.resolveTypeIfNeeded(who.getContentResolver()),token, target != null ? target.mEmbeddedID : null,requestCode, 0, null, options);

此时启动Activity这一操作交给了ActivityManagerNative.getDefault()的startActivity()方法.ActivityManagerNative是一个抽象类,继承了Binder,同时它又实现了IActivityManager接口,其实现类是ActivityManagerService(AMS).

ActivityManagerNative.getDefault()方法返回IActivityManager类型对象,其实现类是ActivityManagerProxy,其构造函数接受一个IBinder类型,其实就是ActivityManagerService对象,此时你应该发现ActivityManagerNative,IActivityManager以及ActivityManagerProxy三者之间的联系如下:

通过上图,我们看到这三者就是一个典型的代理模式:ActivityManagerProxy就是ActivityManagerService的远程代理,那么此时ActivityManagerNative的作用也就很明显:返回AMS的远程代理对象,这样Launcher应用就能和AMS服务通信了.

我们用一张图来简单的描述上述整个流程:

进入ActivityManagerService

现在我们跳到AMS的startActivity()方法继续往下看:

@Overridepublic int startActivity(IBinder whoThread, String callingPackage,Intent intent, String resolvedType, Bundle options) {checkCaller(); int callingUser = UserHandle.getCallingUserId();TaskRecord tr;IApplicationThread appThread; synchronized (ActivityManagerService.this) {tr = mStackSupervisor.anyTaskForIdLocked(mTaskId); if (tr == null) { throw new IllegalArgumentException("Unable to find task ID " + mTaskId);}appThread = ApplicationThreadNative.asInterface(whoThread); if (appThread == null) { throw new IllegalArgumentException("Bad app thread " + appThread);}} //交给mStackSupervisor继续return mStackSupervisor.startActivityMayWait(appThread, -1, callingPackage, intent,resolvedType, null, null, null, null, 0, 0, null, null, null, options, false, callingUser, null, tr);}

首先我们注意到该方法的第一个参数是IBinder类型,其实质就是前边ApplicationThread的实例,也就是ActivityThread中的mAppThread对象.接下来交给ActivityStackSupervisor实例的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) { // Refuse possible leaked file descriptorsif (intent != null && intent.hasFileDescriptors()) { throw new IllegalArgumentException("File descriptors passed in Intent");} boolean componentSpecified = intent.getComponent() != null; // Don't modify the client's object!intent = new Intent(intent); // Collect information about the target of the Intent.ActivityInfo aInfo =resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);ActivityContainer container = (ActivityContainer)iContainer; synchronized (mService) { //省略多行代码int res = startActivityLocked(caller, intent, resolvedType, aInfo,voiceSession, voiceInteractor, resultTo, resultWho,requestCode, callingPid, callingUid, callingPackage,realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,componentSpecified, null, container, inTask); // 省略多行代码return res;}}

该方法看起来非常复杂,但是流程确实蛮清晰的,通过resolveActivity()方法来获取ActivityInfo,接下来是一些其他操作(在不影响流程的前提下,省略多行),然后继续调用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) { int err = ActivityManager.START_SUCCESS; //省略多行代码err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,startFlags, true, options, inTask); return err;}

在该方法中,又继续调用了startActivityUncheckedLocked()方法,抛开其中细节,我们发现该方法中又继续调用了ActivityStack的resumeTopActivityLocked()来继续启动流程:

final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle optio

if (mStackSupervisor.inResumeTopActivity) { // Don't even start recursing.

从上面的代码看出,resumeTopActivitiesLocked()方法继续调用了resumeTopActivityInnerLocked()方法,该方法内部又反过来调用了ActivityStackSupervisor的resumeTopActivitiesLocked()方法

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) { //省略多行代码

在上述代码中,由于应用是第一次启动,因此这里跳过了一些判断代码,最终又调用了ActivityStackSupervisor的startSpecificActivityLocked()来继续启动流程:

void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) { // Is this activity's application already running?

应用是第一次启动,此时系统尚未为其创建进程,因此调用AMS的startProcessLocked()方法,如果该应用已经存在,则调用realStartActivityLocked().由于这里我们的应用第一次启动,所以从startProcessLocked()往下看:

final ProcessRecord startProcessLocked(String processName,

该方法直接调用了其对应的重载方法,并在该其中继续调用了重载方法:

private final void startProcessLocked(ProcessRecord app, String hostingType,

免责声明:本文内容来源于网络或用户投稿,龙泉人才网仅提供信息存储空间服务,不承担相关法律责任。若收录文章侵犯到您的权益/违法违规的内容,可请联系我们删除。
https://www.lqrc.cn/a/rencai/91245.html

  • 关注微信
下一篇:暂无

猜你喜欢

微信公众号