美文网首页
源码分析->Activity启动流程

源码分析->Activity启动流程

作者: 杨0612 | 来源:发表于2020-10-15 15:33 被阅读0次

    https://www.jianshu.com/p/0b12937581b0文章分析了从fork应用进程到Application onCreate执行的过程,有兴趣的同学可以看下。

    下面主要想分析Activity的启动流程
    源码分析基于Android-23

    startActivity(new Intent(this,MainActivity.class))这个启动Activity的代码相信大家应该都很熟悉,它最终会调到

    1.Activity.startActivityForResult

    主要工作:
    判断options是否为空,调用相应的方法,其实两个方法都差不多;这里注意到requestCode为-1,有别于我们平时写的requestCode>=0,-1表示不需要回调到onActivityResult方法;

       @Override
        public void startActivity(Intent intent, @Nullable Bundle options) {
            if (options != null) {
                startActivityForResult(intent, -1, options);
            } else {
                startActivityForResult(intent, -1);
            }
        }
    
    上述startActivityForResult会调到下述重载的startActivityForResult;
    2.Activity.startActivityForResult

    主要工作:
    通过Instrumentation来启动Activity;

    Tips:Instrumentation是一个很有意思类,查看源码可以发现,Activity和Application生命周期的调用都会通过它,它最后会调到AMS当中,设想可以通过反射或者在AndroidManifest配置,利用它来对Activity生命周期进行监控;
    public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
                ......
                Instrumentation.ActivityResult ar =
                    mInstrumentation.execStartActivity(
                        this, mMainThread.getApplicationThread(), mToken, this,
                        intent, requestCode, options);
                ......
    }
    
    3.Instrumentation.execStartActivity

    主要工作:
    (1)ActivityManagerNative.getDefault,从ServiceManager中获取AMS,然后通过asInterface构建AMS代理对象ActivityManagerProxy并返回;
    (2)通过代理来启动Activity,这里面涉及到单例模式Singleton,到此就会转到AMS中;

    Tips:SystemServer启动AMS以后,调用AMS.setSystemProcess方法,将AMS注册到ServiceManager中。
        public ActivityResult execStartActivity(
                Context who, IBinder contextThread, IBinder token, Activity target,
                Intent intent, int requestCode, Bundle options) {
                ......
                int result = ActivityManagerNative.getDefault()
                    .startActivity(whoThread, who.getBasePackageName(), intent,
                            intent.resolveTypeIfNeeded(who.getContentResolver()),
                            token, target != null ? target.mEmbeddedID : null,
                            requestCode, 0, null, options);
                ......
        }
    
    AMS.startActivity最终会调到4.ActivityStackSupervisor.realStartActivityLocked

    主要工作:
    scheduleLaunchActivity,通过app.thread跨进程调用Activity所属的ApplicationThread,

    Tips:app.thread是ProcessRecord的ApplicationThread属性,负责进程间通讯;
       final boolean realStartActivityLocked(ActivityRecord r,
                ProcessRecord app, boolean andResume, boolean checkConfig)
                throws RemoteException {
               ......
                app.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);
                     ......
        }
    
    5.ApplictionThread.scheduleLaunchActivity

    主要工作:
    创建ActivityClientRecord ,最后sendMessage往主线程发送启动Activity的消息(我猜测这里应该是在binder线程,要不然为什么需要转到主线程);

    Tips:ApplictionThread是ActivityThread的内部类;
            public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                    ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                    CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
                    int procState, Bundle state, PersistableBundle persistentState,
                    List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
                    boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
                ......
                ActivityClientRecord r = new ActivityClientRecord();
                ......
                sendMessage(H.LAUNCH_ACTIVITY, r);
            }
    
    ActivityThread.H.handleMessage会调用到6.ActivityThread.handleLaunchActivity

    主要工作:
    (1)WindowManagerGlobal.initialize,初始化WMS客户端代理,为后续添加窗口做准备;
    (2)performLaunchActivity,主要是创建Activity、调用onCreate以及onStart方法;
    (3)handleResumeActivity,调用onResume,还包括一个很关键的,通知绘制界面,它涉及点比较多,这里就不展开了。

    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
            ......
            WindowManagerGlobal.initialize();
            Activity a = performLaunchActivity(r, customIntent);
                ......
            handleResumeActivity(r.token, false, r.isForward,
                        !r.activity.mFinished && !r.startsNotResumed);
             ......
        }
    
    7.ActivityThread.performLaunchActivity

    主要工作:
    (1)getPackageInfo,获取包信息,返回类型是LoadedApk,它封装了Application信息、资源路径、lib路径;
    (2)mInstrumentation.newActivity,根据类型反射实例化Activity对象;

    Tips:反射调用的是无参的构造函数,如果给Activity定义了一个有参的构造函数,一定要再定义的一个无参的构造函数,要不然这里会报错;

    (3)r.packageInfo.makeApplication,会调到LoadedApk.makeApplication,如果当前Activity的Application为空,则反射构建Application对象并调用其onCreate方法,否则直接返回;
    (4)activity.attach,这方法很重要,给Activity mBase属性赋值以及创建PhoneWindow;
    (5)mInstrumentation.callActivityOnCreate,调用Activity onCreate方法;
    (6)activity.performStart,最终也是通过Instrumentation来调用onStart方法;
    (7)当r.state不为空,则调用mInstrumentation.callActivityOnRestoreInstanceState;
    (8)mActivities.put(r.token, r),将ActivityClientRecord放入集合;

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
            ActivityInfo aInfo = r.activityInfo;
            if (r.packageInfo == null) {
                r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                        Context.CONTEXT_INCLUDE_CODE);
            }
           ......
            Activity activity = null;
           ......
            activity = mInstrumentation.newActivity(
                        cl, component.getClassName(), r.intent);
    
            try {
                Application app = r.packageInfo.makeApplication(false, mInstrumentation);
               ......
                if (activity != null) {
                    ......
                    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);
                    ......
                    if (r.isPersistable()) {
                        mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                    } else {
                        mInstrumentation.callActivityOnCreate(activity, r.state);
                    }
                     ......
                     activity.performStart();
                      ......                                                 
                      mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                    }
                      ...... 
                }
                      ...... 
            } 
              ...... 
            mActivities.put(r.token, r);
            return activity;
        }
    

    至此Activity的onCreate、onStart方法就被调用,也就是启动起来了。

    补充看下Activity.attach方法
    Activity.attach

    主要工作:
    (1)attachBaseContext,给Activity mBase变量赋值,我们获取Resource对象其实通过它;
    (2)new PhoneWindow(this),这个大家都很熟悉了,就是PhoneWindow;
    (3)mWindow.setCallback(this),Activity作为mWindow的监听器,当有事件分发到Window,Activity也就能接受事件;

    final void attach(Context context, ActivityThread aThread,
                Instrumentation instr, IBinder token, int ident,
                Application application, Intent intent, ActivityInfo info,
                CharSequence title, Activity parent, String id,
                NonConfigurationInstances lastNonConfigurationInstances,
                Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
            attachBaseContext(context);
            .....
            mWindow = new PhoneWindow(this);
            .....
            mWindow.setCallback(this);
            .....
        }
    
    Activity启动流程.png
    总结:

    (1)启动Activity最终会调用startActivityForResult,接着调到Instrumention,通过ActivityManagerNative获取AMS的客户端代理ActivityManagerProxy,通过代理跨进程通讯到AMS,AMS对LaunchMode 、intent等进行处理后,通过ApplicationThreadProxy跨进程通讯到该Activity所属的ApplicationThread,通过sendMessage转到主线程,调到handleLaunchActivity,内部执行performLaunchActivity创建Activity以及给mBase赋值,最终通过Instrumention调用Activity的声明周期方法;
    (2)ActivityManagerServices、ApplicationThread、ActivityThread、Instrumention四者之间的关系,AMS负责管理Activity生命周期,需要对生命周期进行调度时通知到进程的ActivityThread,而真正的调用者是Instrumention,它是进程单例的,ApplicationThread是负责AMS跨进程通讯到ActivityThread的。
    (3)Activity的引用链关系,ActivityThead的mActivities属性保存没有被销毁的ActivityClientRecord,ActivityClientRecord持有Activity的引用,ActivityThead-> ActivityClientRecord->Activity;

    Tips:ActivityClientRecord与ActivityRecord,都是描述Activity,只不过前者是在app端使用,后者是在AMS端使用。

    (4)无论是App跨进程通讯到AMS,还是AMS跨进程通讯到App,都是采用binder通讯,当App跨进程通讯到AMS,App端就是Client端,而AMS就是Server端,两者都对共同的接口IActivityManager,只不过Client端是代理,真正的实现是在Server,所以这里采用了代理模式。
    (5)遇到问Activity启动流程的面试题,建议重点讲下fork进程、创建Application以及Activity、调用他们的生命周期。

    以上分析有不对的地方,请指出,互相学习,谢谢哦!

    相关文章

      网友评论

          本文标题:源码分析->Activity启动流程

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