深入浅出Activity的启动过程

一、Activity的生命周期

对于每个Android开发者来说,Activity的生命周期最熟悉不过了,这里简单引用一下Android API文档上的生命周期图。但是Activity的几个主要生命周期是如何回调的呢?请看下面Activity的启动流程部分。

f

二、Activity的启动流程

Activity的启动一般我们是通过startActivity(Intentent),为了分析主流程,这里暂时以Activity的冷启动来分析。跟进startActivity()的内部,看看具体是如何startActivity的,在Activity中startActivity通过前面几次方法的内部调用,会走到下面方法,伪代码如下:

public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
        if (mParent == null) {
            ...
            //冷启动走这里
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
        } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                // Note we want to go through this method for compatibility with
                // existing applications that may have overridden it.
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

核心方法在Instrumentation的exeStartActivity方法,该方法中通过AMS的binder对象调用AMS中的startActivity方法,代码块如下

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        ...
        //核心方法通过AMS的binder对象调用AMS中的startActivity方法
        int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, null, options);
    }

这里AMS的binder对象调用会通过mRemote.transact(START_ACTIVITY_TRANSACTION, data, relplay, 0)来调用到ActivityManagerNative中的onTransact()方法,如下

@Override
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        switch (code) {
        case START_ACTIVITY_TRANSACTION:
        {
            ...
            //核心方法startActivity
            int result = startActivity(app, callingPackage, intent, resolvedType,
                    resultTo, resultWho, requestCode, startFlags,
                    profileFile, profileFd, options);
            return true;
        }
        ...
}

上面核心方法startActivity最后走到AMS中的startActivity方法,方法如下 

public final int startActivity(IApplicationThread caller, String callingPackage,
                                   Intent intent, String resolvedType, IBinder resultTo,
                                   String resultWho, int requestCode, int startFlags,
                                   String profileFile, ParcelFileDescriptor profileFd, Bundle options) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode,
                startFlags, profileFile, profileFd, options, UserHandle.getCallingUserId());
    }
startActivityAsUser的实现如下
@Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
                                         Intent intent, String resolvedType, IBinder resultTo,
                                         String resultWho, int requestCode, int startFlags,
                                         String profileFile, ParcelFileDescriptor profileFd, Bundle options, int userId) {
       
        ...
        //核心方法调用
        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
                null, null, options, userId);
    }

这里ActivityStackSupervisor我理解为一个Activity的辅助类,这里省去中间一些跳转,最终于调用startSpecificActivityLocked

在com.android.server.am.ActivityStackSupervisor.java中

void startSpecificActivityLocked(ActivityRecord r,
                                     boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
        //查询该Activity所对应的进程是否启动
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

        //在ProcessRecord不为null说明进程已经存在,app.thread != null,说明应用向AMS注册过IApplicationThread.
        if (app != null && app.thread != null) {
            realStartActivityLocked(r, app, andResume, checkConfig);
        }

        //否则启动进程,在AMS中启动
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }

当进程不存在的时候则执行mService.startProcessLocked(),即在AMS中执行,方法如下

private final void startProcessLocked(ProcessRecord app,
                                          String hostingType, String hostingNameStr) {
        ...
        // Start the process.  It will either succeed and return a result containing
        // the PID of the new process, or else throw a RuntimeException.
        //android.app.ActivityThread为进程启动入口函数类, Process.start()向Zygote发送一个启动进程的请求
        Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
                app.processName, uid, uid, gids, debugFlags, mountExternal,
                app.info.targetSdkVersion, app.info.seinfo, null);

        ...
        synchronized (mPidsSelfLocked) {
            this.mPidsSelfLocked.put(startResult.pid, app);
            Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
            msg.obj = app;
            //如果应用进程启动后,在一定时间内没有向AMS来报告就会超时,10秒,
            // 如果超时,AMS则会清理应用的相关信息(如该进程启动的一些应用组件)
            mHandler.sendMessageDelayed(msg, startResult.usingWrapper
                    ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
        }
    }

这里继续看一下Process.start()是如何启动进程的

public static final ProcessStartResult start(final String processClass,
                                  final String niceName,
                                  int uid, int gid, int[] gids,
                                  int debugFlags, int mountExternal,
                                  int targetSdkVersion,
                                  String seInfo,
                                  String[] zygoteArgs) {
            return startViaZygote(processClass, niceName, uid, gid, gids,
    }

private static ProcessStartResult startViaZygote(final String processClass,
                                                     final String niceName,
                                                     final int uid, final int gid,
                                                     final int[] gids,
                                                     int debugFlags, int mountExternal,
                                                     int targetSdkVersion,
                                                     String seInfo,
                                                     String[] extraArgs) {
        ...
        return zygoteSendArgsAndGetResult(argsForZygote);
    }
zygoteSendArgsAndGetResult()已经执行到Zygote端了,实际上是Zygote进程的Loop循环中调用了进程启动的方法runOnce()函数,从而启动APP应用进程。进一步会调用到ActivityThread的main函数
public static void main(String[] args) {
        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();

        //这里会向AMS报告,按前面Handler sendMessage 10秒超时,如果在10少还没有来得及注册,那AMS则会清理掉该进程的相关信息
        thread.attach(false, startSeq);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

上面说这么多,关于startActivity时启动进程的流程,这里通过一张图来总结一下AMS、Zygote、应用之间的通信关系

应用程序向AMS作attachApplication操作的实现如下,已在注释中说明清楚

private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {
        ...
        //根据进程pid获取进程
        ProcessRecord app = mPidsSelfLocked.get(pid);

        ...
        //thread为应用端注册到AMS的binder对象
        //应用端作一些初始化,比如初始化Application
        thread.bindApplication(processName, appInfo,...);

        ...
        //下面这三步处理启动进程时挂起的一些应用组件
        //处理挂起的Activity组件
        mStackSupervisor.attachApplicationLocked(app, mHeadless);
        ...
        //处理挂起的Service组件
        mServices.attachApplicationLocked(app, processName);
        ...
        //处理挂起的广播组件
        sendPendingBroadcastsLocked(app);
        
        return true;
    }

这里以Launcher启动应用为例子,当Launcher发起startActivity时,由AMS向检测进程是否启动,如果没有启动,则发起启动进程的请求startProcessLocked,进入Zygote的runOnce()函数fork出应用进程,然后调用ActivityThread的main()函数开始Application向AMS注册,即attachApplication,继续后面的bindApplication, makeApplication。从而进程启动完成。

当进程启动完成后,就是真正的启动Activity了,即执行realStartActivityLocked()。看看realStartActivityLocked()是什么样的。

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) {

        ...
        //这里app对应ProcessLocked,即应用进程
        //app.thread对应ApplicationThread,即应用程序启动时册到AMS的binder对象
        app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                System.identityHashCode(r), r.info,
                new Configuration(mService.mConfiguration), r.compat,
                app.repProcState, r.icicle, results, newIntents, !andResume,
                mService.isNextTransitionForward(), profileFile, profileFd,
                profileAutoStop);

        ...
        return true;
    }

上面scheduleLaunchActivity最后会调用到ActivityThread中的scheduleLaunchActivity(),具体如下

public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                                                 ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
                                                 int procState, Bundle state, List<ResultInfo> pendingResults,
                                                 List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
                                                 String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
            ...
            ActivityClientRecord r = new ActivityClientRecord();
            ...
            //给主线程发送一个启动Activity的消息
            sendMessage(H.LAUNCH_ACTIVITY, r);
        }

public void handleMessage(Message msg) {
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    ActivityClientRecord r = (ActivityClientRecord) msg.obj;
                    handleLaunchActivity(r, null);
                }
                break;
}

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);
        }
            
    }

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ...
        //1、调用到Activity生命在中的onCreate()方法,内部通过ClassLoader加载Activity到实例
        //2、中间还会检测Application, 创建Activity的上下文,实际就是Application中的mBase
        //3、然后通过Instrumentation中的callActivityOnCreate()调用到onCreate(),以及Instrumentation的callActivityOnStart()调用到onStart()
        Activity a = performLaunchActivity(r, customIntent);

        ...
        if (a != null) {
            //这里实际上会调用到我们平常看到的Activity中的生命周期方法onResume()
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);
        }

    }

经过上面步骤,很清楚的看到Activity的主要生命周期方法onCreate()、onStart()、onResume()是在何时调用。用一张图来总结Activity在启动进程后如何realStartActivityLock()的

对于整个Activity的启动,其实可以一句话总结:先判断Activity的进程有没有启动,如果没有走启动进程的流程,否则走真正启动Activity的流程。

Activity的启动看似很复杂,其实核心流利就两个,就是上面的两张图表示。

发布了11 篇原创文章 · 获赞 3 · 访问量 774

猜你喜欢

转载自blog.csdn.net/xj_hnust/article/details/97658963