Android进阶3:Activity源码分析(1) —— Activity启动流程(8.0)

前言

关于Activity的源码分析,看了足足有半个月,理由就是:
1:Activity源代码很多,逻辑很复杂
2:下班再能加班学习,礼拜天抽空学习源码
至于为什么看源码:因为偶尔看到一句话:不懂Activity的onCreate的内部源码,你敢说你是Android开发程序猿?!

其实关于这篇文章,我想了很久,不太敢贸然写,因为牵涉的类有点多并且复杂,怕理解出错,给各位小伙伴带来困扰,经过学习了两个礼拜,学到了一点东西,总结一下。
首先Activity的启动切入点有两个,startActivity切入和ActivityThread的main方法切入,最终的效果都是开启一个新的Activity。 本篇文章先从ActivityThread的main方法切入分析。

ActivityThread的Main方法入口

通常我们启动一个App,首先都是先创建一个进程,然后AMS调度,进入到ActivityThread的main方法中,ActivityThread类通常就是我们说的UI线程(主线程),一个进程对应一个ActivityThread,用于调度Activity的生命周期,Service的生命周期,以及调度Instrumentation的创建。看下main源码:

   public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
        SamplingProfilerIntegration.start();

        // CloseGuard defaults to true and can be quite spammy.  We
        // disable it here, but selectively enable it later (via
        // StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);

        Environment.initForCurrentUser();

        // Set the reporter for event logging in libcore
        EventLogger.setReporter(new EventLoggingReporter());

        // Make sure TrustedCertificateStore looks in the right place for CA certificates
        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
        TrustedCertificateStore.setDefaultUserDirectory(configDir);

        Process.setArgV0("<pre-initialized>");

        //注意点1:创建主线程的Looper
        Looper.prepareMainLooper();

        //创建ActivityThread类
        ActivityThread thread = new ActivityThread();
        //注意点2:
        thread.attach(false);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        // End of event ActivityThreadMain.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        //开始主线程消息调度
        Looper.loop();

        //注意点3:不能够退出主线程Looper
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

通过Main方法,看下三个注意点:

  1. 创建主线程的Looper对象;在之前学习Handler,Looper源码的时候,没有初始化Looper,都能够实现消息调度。
  2. 调用了ActivityThread的attach方法
  3. 不能够退出主线程UI,如果如果退出,就报错,因为我们知道,开启looper消息循环之后,Looper.loop()之后的代码是不会执行的,因为如果退出了主线程,那么App自动就死了,所以就提示报错。

进入ActivityThread的attach方法。

    private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            ViewRootImpl.addFirstDrawHandler(new Runnable() {
                @Override
                public void run() {
                    ensureJitEnabled();
                }
            });
            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                    UserHandle.myUserId());
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            //创建获得IActivityManager的代理对象ActivityManagerService
            final IActivityManager mgr = ActivityManager.getService();
            try {
                //创建applicaiton
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
            ....
    }

先看下,ActivityManager.getService(),进入该方法:

    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

    //单例模式
    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    //获取一个关联了系统服务ActivityManagerService的Binder对象
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    //获取IActivityManager的代理对象,基于binder机制,通过调用代理对象的方法,从而使ActivityManagerService对象的方法被调用.
                    //注意:ActivityManagerService继承自IActivityManager.Stub。
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

getService()内部调用的是IActivityManagerSingleton的get方法,大体来说,IActivityManagerSingleton是一个单例对象,再看onCreate方法,方法内部首先通过ServiceManager获得Activity_Service的注册服务。返回IBinder对象,至此,我们应该知道了,其实和底层交互数据的原理就是Binder机制。

先说下Binder机制,我们知道Binder机制由四部分组成:客户端,服务端,ServiceManager管理以及Binder驱动。其中前三个运行在用户层,Binder驱动运行在内核层,然后服务端实现IBinder方法,成为代理对象,底层的各种的ManagerService都会在ServiceManager,通过ServiceManager统一获得各种服务端Binder对象。至于Binder机制,建议各位同学去看下Binder源码。在此不再赘述。

我们知道ActivityManagerService继承字IActivityManager.Stub,所以本身来说他就是一个Binder对象。所以getService()方法本身返回的就是一个代理对象,通过调用代理对象的方法,从而调用AMS(ActivityManagerService的简称)的方法。

接下来回到attach方法,调用了AMS的attachApplication方法,源码示下:

    private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {

        ......
            if (app.instr != null) {
                thread.bindApplication(processName, appInfo, providers,
                        app.instr.mClass,
                        profilerInfo, app.instr.mArguments,
                        app.instr.mWatcher,
                        app.instr.mUiAutomationConnection, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.persistent,
                        new Configuration(getGlobalConfiguration()), app.compat,
                        getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial);
            } else {
                //通过代理对象ApplicationThread调用其方法bindApplication方法;
                thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                        null, null, null, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.persistent,
                        new Configuration(getGlobalConfiguration()), app.compat,
                        getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial);
            }

            .....

        // See if the top visible activity is waiting to run in this process...
        if (normalMode) {
            try {
            //注意点2:
                if (mStackSupervisor.attachApplicationLocked(app)) {
                    didSomething = true;
                }
            ....
    }

首先看到上述代码:调用了thread.bindApplication(….)方法,thread是个IApplicationThread代理对象,又是Binder机制。。。实际上,AMS向上层UI主线程的控制是通过ApplicationThread的调度,ApplicaitonThread是ActivityThread的内部类,继承了IAppllication.Stub,是个Binder类,所以调用thread.bindApplicaiton(), 实际上调用的是ApplicationThread的bindApplication()方法;
至于注意点2: 我们下文再分析

进入到ApplicationThread $ bindApplication :

        public final void bindApplication(String processName, ApplicationInfo appInfo,
                List<ProviderInfo> providers, ComponentName instrumentationName,
                ProfilerInfo profilerInfo, Bundle instrumentationArgs,
                IInstrumentationWatcher instrumentationWatcher,
                IUiAutomationConnection instrumentationUiConnection, int debugMode,
                boolean enableBinderTracking, boolean trackAllocation,
                boolean isRestrictedBackupMode, boolean persistent, Configuration config,
                CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
                String buildSerial) {

            .....
            sendMessage(H.BIND_APPLICATION, data);
        }

发送Message, 继续跟进:handleBindApplication :

    private void handleBindApplication(AppBindData data) {

       ....

        //获取APK的相关信息,比如:包名,版本号等信息;
        data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);

       .....

        //创建ContextImpl(该类继承自抽象类Context)
        final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
        updateLocaleListFromAppContext(appContext,
                mResourcesManager.getConfiguration().getLocales());

       .....

        // Continue loading instrumentation.
        if (ii != null) {
            final ApplicationInfo instrApp = new ApplicationInfo();
            ii.copyTo(instrApp);
            instrApp.initForUser(UserHandle.myUserId());
            // 获取APP信息
            final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                    appContext.getClassLoader(), false, true, false);
            final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);

            try {
                final ClassLoader cl = instrContext.getClassLoader();
                //注意点1:通过反射创建Instrumentation对象
                mInstrumentation = (Instrumentation)
                    cl.loadClass(data.instrumentationName.getClassName()).newInstance();
            }

            ......

        try {

            //注意点2:创建Application
            Application app = data.info.makeApplication(data.restrictedBackupMode, null);
            mInitialApplication = app;

           .....

            try {
            //注意点3:调用Application的onCreate方法
                mInstrumentation.callApplicationOnCreate(app);
            } 
            ......
    }

看下注意点:

  1. 通过反射创建Instrumentation对象,首先,对于Instrumentation的作用,先不深谈,我们只要知道创建Instrumentation的位置。
  2. data.info.makeApplication(…) 这里data.info 也就是LoadedAPK类的对象。
  3. 调用了Instrumentation的callApplicationOnCreate方法。

首先说下注意点看,进入到LoadedApk $ makeApplication(…)

    public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        //整个应用内,只有一个Application对象
        if (mApplication != null) {
            return mApplication;
        }

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");

        Application app = null;

        String appClass = mApplicationInfo.className;
        if (forceDefaultAppClass || (appClass == null)) {
            appClass = "android.app.Application";
        }

        try {
            java.lang.ClassLoader cl = getClassLoader();
            if (!mPackageName.equals("android")) {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                        "initializeJavaContextClassLoader");
                initializeJavaContextClassLoader();
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            }
            //调用Instrumentation的newApplication方法。
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } 

        ......

    }

上述代码,首先判断mApplication是否为null, 不为null,就直接返回,这就是为什么一个应用只有一个Application对象(单进程), 为null的话,调用了Instrumentation的newApplication方法。
进入到Instrumentation $ newApplication方法

    static public Application newApplication(Class<?> clazz, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        //通过反射创建了Application对象
        Application app = (Application)clazz.newInstance();
        app.attach(context);
        return app;
    }

newApplication做的事只有两件,首先通过反射创建Application对象,并且调用其attach方法,返回该对象。再次注意一下:Application是在Instrumentation中创建的。

再回到ActivityThread的handleBindApplication方法,接下来看下注意点3:进入到Instrumentation $ callApplicationOnCreate方法:

    public void callApplicationOnCreate(Application app) {
        app.onCreate();
    }

调用了,就一句话:调用了Application的onCreate方法。
解释了:为什么我们一般都在Application的onCreate方法中初始化一些第三方,因为它最早被创建啊!

至此Application的创建就完成了,那么Activity页面呢?

回到AMS的attachApplicationLocked方法:看下注意点2,调用了ActivityStackSupervisor类的attachApplicationLocked方法:


    boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {

        ....

        //
         if (realStartActivityLocked(hr, app, true, true)) {
                   didSomething = true;
          }
         ....
    }

进入realStartActivityLocked(….)方法,

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

        ......

            /*
            通过binder机制,通过代理调用ApplicationThread的scheduleLaunchActivity方法。将启动Activity的操作交给ApplicationThread类
             */
            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info,
                    // TODO: Have this take the merged configuration instead of separate global and
                    // override configs.
                    mergedConfiguration.getGlobalConfiguration(),
                    mergedConfiguration.getOverrideConfiguration(), r.compat,
                    r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                    r.persistentState, results, newIntents, !andResume,
                    mService.isNextTransitionForward(), profilerInfo);

            .......

    }

调用了Application的ApplicationThread的scheduleLaunchActivity(…)方法,进入 ApplicationThread$scheduleLaunchActivity(…):

        @Override
        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) {

            updateProcessState(procState, false);

            //用于封装启动Activity一些参数值
            ActivityClientRecord r = new ActivityClientRecord();

            r.token = token;
            r.ident = ident;
            r.intent = intent;
            r.referrer = referrer;
            r.voiceInteractor = voiceInteractor;
            r.activityInfo = info;
            r.compatInfo = compatInfo;
            r.state = state;
            r.persistentState = persistentState;

            r.pendingResults = pendingResults;
            r.pendingIntents = pendingNewIntents;

            r.startsNotResumed = notResumed;
            r.isForward = isForward;

            r.profilerInfo = profilerInfo;

            r.overrideConfig = overrideConfig;
            updatePendingConfiguration(curConfig);

            //发送消息
            sendMessage(H.LAUNCH_ACTIVITY, r);
        }

发送消息,进入ActivityThead的handleLaunchActivity方法:

    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        ......

        //注意点1:启动Activity
        Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            reportSizeConfigurations(r);
            Bundle oldState = r.state;
            // 注意点2:
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);

            ......

    }

上述代码标注了两个注意点,先看下注意点1的方法, 进入 performLaunchActivity方法:


    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {

        ......

        //获取要启动的Activity的ComponentName对象
        ComponentName component = r.intent.getComponent();
        if (component == null) {
            component = r.intent.resolveActivity(
                mInitialApplication.getPackageManager());
            r.intent.setComponent(component);
        }

       .......

        //创建Activity的上下文环境(ContentImpl继承自Context)
        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            //通过类加载器创建Activity对象
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);

            .......

        }

        //获取Application对象
        try {
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

            ......

                //初始化Activity类里的一些数据
                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, window, r.configCallback);

                if (customIntent != null) {
                    activity.mIntent = customIntent;
                }
                r.lastNonConfigurationInstances = null;
                checkAndBlockForNetworkAccess();
                activity.mStartedActivity = false;
                int theme = r.activityInfo.getThemeResource();
                //Activity设置主题
                if (theme != 0) {
                    activity.setTheme(theme);
                }

                activity.mCalled = false;
                //启动Activity
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onCreate()");
                }
                r.activity = activity;
                r.stopped = true;
                //判断是否是结束Activity
                if (!r.activity.mFinished) {
                    activity.performStart();
                    r.stopped = false;
                }
                if (!r.activity.mFinished) {
                    if (r.isPersistable()) {
                        if (r.state != null || r.persistentState != null) {
                            mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                    r.persistentState);
                        }
                    } else if (r.state != null) { //刚进来的Activity bundle数据为null

                        //r.state 也就是我们保存的Bundle对象,要恢复的数据
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                    }
                }

                ......

    }

在该方法里,比较重要的就是首先调用了Instrumentation的newActivity方法,进入到该方法,

   public Activity newActivity(Class<?> clazz, Context context, 
            IBinder token, Application application, Intent intent, ActivityInfo info, 
            CharSequence title, Activity parent, String id,
            Object lastNonConfigurationInstance) throws InstantiationException, 
            IllegalAccessException {
        Activity activity = (Activity)clazz.newInstance();
        ActivityThread aThread = null;
        activity.attach(context, aThread, this, token, 0 /* ident */, application, intent,
                info, title, parent, id,
                (Activity.NonConfigurationInstances)lastNonConfigurationInstance,
                new Configuration(), null /* referrer */, null /* voiceInteractor */,
                null /* window */, null /* activityConfigCallback */);
        return activity;
    }

通过反射创建了Activity。至此我们在注意下:在Instrumentation中创建Activity对象。

返回performLaunchActivity方法:创建Activity之后,设置主题,然后调用了Instrumentation的callActivityOnCreate方法,进入该方法:

    public void callActivityOnCreate(Activity activity, Bundle icicle) {
        prePerformCreate(activity);
        activity.performCreate(icicle);
        postPerformCreate(activity);
    }

调用了performCreate方法,进入Activity $ performCreate :


    final void performCreate(Bundle icicle) {
        restoreHasCurrentPermissionRequest(icicle);
        //    onCreate方法回调
        onCreate(icicle);
        mActivityTransitionState.readState(icicle);
        performCreateCommon();
    }

(⊙﹏⊙),至此onCreate方法算是执行到了,那么onStart和onResume方法呢?继续探究。。。

再次回到 performLaunchActivity方法中, 调用了 performStart()方法,进入方法内:

    final void performStart() {
        .....
        mInstrumentation.callActivityOnStart(this);
        .....
    }

接下来还是通过调用了Instrumentation的callActivityOnStart()方法,内部再调用Activity的onStart()方法。
至此onStart方法调用了,那么 onResume呢? 继续深究。。。

返回到handleLaunchActivity方法中,看下注意点2,进入到handleResumeActivity方法内:


    final void handleResumeActivity(IBinder token,
            boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
        ......
        r = performResumeActivity(token, clearHide, reason);

            .......
            // Tell the activity manager we have resumed.
            if (reallyResume) {
                try {
                //Activity A 跳转到 Activity B ,当ActivityB创建并显示完毕之后,开始Activity A的onPauseme
                    ActivityManager.getService().activityResumed(token);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            }
            ......

进入到performResumeActivity方法:


    public final ActivityClientRecord performResumeActivity(IBinder token,
            boolean clearHide, String reason) {
        ......
        r.activity.performResume();
        ......
    }

进入到Activity $ performResume:


    final void performResume() {
        //是否是重新启动Activity
        performRestart();

        mFragments.execPendingActions();

        mLastNonConfigurationInstances = null;

        mCalled = false;
        // mResumed is set by the instrumentation
        mInstrumentation.callActivityOnResume(this);
        .....
    }

看见调用了Instrumentation的callActivityOnResume方法,还是通过Instrumentation间接调用Activity的回调方法。

    public void callActivityOnResume(Activity activity) {
        activity.mResumed = true;
        //调用了Activity的onResume方法:
        activity.onResume();

        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    am.match(activity, activity, activity.getIntent());
                }
            }
        }
    }

至此开启APP从ActivityThread的main方法入口开始,Activity的启动流程就分析完了。

下一篇分析另一个切入点:Activity的startActivity方法以及Activity的销毁流程(finish)
Android进阶3:Activity源码分析(2) —— Activity启动和销毁流程(8.0)

如果文章有错,感谢小伙伴指正,谢谢O(∩_∩)O。

Android学习交流群:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/lmq121210/article/details/82694781