美文网首页
源码分析Activity的启动过程

源码分析Activity的启动过程

作者: 空山Echo | 来源:发表于2019-05-23 15:01 被阅读0次

    当我们启动一个Activity,都将通过startActivityForResult去开始Activity的启动过程。

    1. startActivityForResult方法(Activity.java)

    在startActivityForResult方法中一个重要方法execStartActivity
    execStartActivity方法就像一个魔盒,后续的启动过程跟它的调用者、参数都息息相关

     public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
                @Nullable Bundle options) {
            if (mParent == null) {
                options = transferSpringboardActivityOptions(options);
                Instrumentation.ActivityResult ar =
                    mInstrumentation.execStartActivity(
                        this, mMainThread.getApplicationThread(), mToken, this,
                        intent, requestCode, options);
                ...
            }
          ...
    }
    

    2. execStartActivity方法(Instrumentation.java)

    • 在execStartActivity方法中启动Activity的实现交由ActivityManager.getService()的startActivity方法完成。ActivityManager.getService()得到的就是AMS(ActivityManagerService),是一个Binder。
    • 并且会调用checkStartActivityResult方法检查启动结果
    public ActivityResult execStartActivity(
                Context who, IBinder contextThread, IBinder token, Activity target,
                Intent intent, int requestCode, Bundle options) {
            IApplicationThread whoThread = (IApplicationThread) contextThread;
            ...
            try {
                intent.migrateExtraStreamToClipData();
                intent.prepareToLeaveProcess(who);
                int result = ActivityManager.getService()
                    .startActivity(whoThread, who.getBasePackageName(), intent,
                            intent.resolveTypeIfNeeded(who.getContentResolver()),
                            token, target != null ? target.mEmbeddedID : null,
                            requestCode, 0, null, options);
                checkStartActivityResult(result, intent);
            } catch (RemoteException e) {
                throw new RuntimeException("Failure from system", e);
            }
            return null;
        }
    

    3. 由此启动过程转移到AMS的startActivity中

    此方法中会调用一系列方法。最终以ActivityStackSupervisor的realStartActivityLocked方法为启动的关键方法,继续启动过程

    4. realStartActivityLocked方法(AMS ---->ActivityStackSupervisor.java)

    在此方法中调用这样的一段代码app.thread.scheduleLaunchActivity(),并把AMS这边对这个Activity的记录各方面信息当做参数,这样客户端就能获取到Activity的各种信息即ActivityClientRecord。

    • app.thread实际就是ActivityThread的内部类ApplicationThread。也就是调用execStartActivity方法传递的参数mMainThread.getApplicationThread()
    • 由此启动过程从服务又回到客户端了
    //ActivityStack类
    final boolean realStartActivityLocked(ActivityRecord r,
            ProcessRecord app, boolean andResume, boolean checkConfig)
            throws RemoteException {
        //...  
        try {
            //...
            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info,
                    new Configuration(mService.mConfiguration),
                    r.compat, r.icicle, results, newIntents, !andResume,
                    mService.isNextTransitionForward(), profileFile, profileFd,
                    profileAutoStop);
            //...
        } catch (RemoteException e) {
            //...
        }
        //...    
        return true;
    }
    

    5. scheduleLaunchActivity() (ActivityThread.java)

    这个方法保存Activity相关信息后,完成一件事:向名为H的Handler发送一条启动消息,接下来Handler H将对“LAUNCH_ACTIVITY”这个消息进行处理,交由handleLaunchActivity方法实现。

    //ActivityThread类
    public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
            ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
            Bundle state, List<ResultInfo> pendingResults,
            List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
            String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
        ActivityClientRecord r = new ActivityClientRecord();
        r.token = token;
        r.ident = ident;
        r.intent = intent;
        r.activityInfo = info;
        r.compatInfo = compatInfo;
        r.state = state;
        r.pendingResults = pendingResults;
        r.pendingIntents = pendingNewIntents;
        r.startsNotResumed = notResumed;
        r.isForward = isForward;
        r.profileFile = profileName;
        r.profileFd = profileFd;
        r.autoStopProfiler = autoStopProfiler;
        updatePendingConfiguration(curConfig);
        queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
    }
    

    6. handleLaunchActivity方法(ActivityThread.java)

    由H Handler处理消息也意味着启动过程到了主线程中

    • 此方法中将调用performLaunchActivity方法最终完成Activity对象的创建和启动过程
      public Activity handleLaunchActivity(ActivityClientRecord r,
                PendingTransactionActions pendingActions, Intent customIntent) {
            // If we are getting ready to gc after going to the background, well
            // we are back active so skip it.
            ...
            final Activity a = performLaunchActivity(r, customIntent);
    
            ...
            return a;
        }
    

    7. performLaunchActivity方法(ActivityThread.java)

    完成以下几件事

    1. 从ActivityClientRecord中获取待启动Activity组件的信息
    2. 通过Instrumentation的newActivity方法使用类加载器创建Activity对象
    3. 通过LoadedApk的makeApplication方法尝试创建Application对象
    4. 创建ContextImpl对象并通过attach方法来完成一些重要数据的初始化(由attach方法ContextImpl与Activity建立关联)
    5. 调用Activity的onCreate方法

    这样就完成了整个启动过程

    1. 新的Activity何时被创建
    2. Activity的onCreate方法何时被系统回调?
      https://www.jianshu.com/p/4edf1987a940

    相关文章

      网友评论

          本文标题:源码分析Activity的启动过程

          本文链接:https://www.haomeiwen.com/subject/eqeeaqtx.html