Android進階3:Activity源碼分析(1) —— Activity啓動流程(8.0)

關於Activity的源碼分析,看了足足有半個月,理由就是:
1:Activity源代碼不少,邏輯很複雜
2:下班再能加班學習,禮拜天抽空學習源碼
至於爲何看源碼:由於偶爾看到一句話:不懂Activity的onCreate的內部源碼,你敢說你是Android開發程序猿?!java

其實關於這篇文章,我想了好久,不太敢貿然寫,由於牽涉的類有點多而且複雜,怕理解出錯,給各位小夥伴帶來困擾,通過學習了兩個禮拜,學到了一點東西,總結一下。
首先Activity的啓動切入點有兩個,startActivity切入和ActivityThread的main方法切入,最終的效果都是開啓一個新的Activity。 本篇文章先從ActivityThread的main方法切入分析。
ActivityThread的Main方法入口android

一般咱們啓動一個App,首先都是先建立一個進程,而後AMS調度,進入到ActivityThread的main方法中,ActivityThread類一般就是咱們說的UI線程(主線程),一個進程對應一個ActivityThread,用於調度Activity的生命週期,Service的生命週期,以及調度Instrumentation的建立。看下main源碼:app

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

        // 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);oop

        Environment.initForCurrentUser();源碼分析

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

        // 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>");ui

        //注意點1:建立主線程的Looper
        Looper.prepareMainLooper();this

        //建立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方法,看下三個注意點:

    建立主線程的Looper對象;在以前學習Handler,Looper源碼的時候,沒有初始化Looper,都可以實現消息調度。
    調用了ActivityThread的attach方法
    不可以退出主線程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);
            }
            ......
    }

   

看下注意點:

    經過反射建立Instrumentation對象,首先,對於Instrumentation的做用,先不深談,咱們只要知道建立Instrumentation的位置。
    data.info.makeApplication(…) 這裏data.info 也就是LoadedAPK類的對象。
    調用了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。  

相關文章
相關標籤/搜索