android Activity啓動流程

Activity的啓動過程,我們可以從Context的startActivity說起,其實現是ContextImpl的startActivity,然後內部會通過Instrumentation來嘗試啓動Activity,這是一個跨進程過程,它會調用ams的startActivity方法,當AMS校驗完activity的合法性後,會通過ApplicationThread回調到我們的進程,這也是一次跨進程過程,而applicationThread就是一個binder,回調邏輯是在binder線程池中完成的,所以需要通過Handler H將其切換到ui線程,第一個消息是LAUNCH_ACTIVITY,它對應handleLaunchActivity,在這個方法裏完成了Activity的創建和啓動,接着,在activity的onResume中,activity的內容將開始渲染到window上,然後開始繪製直到我們看見(摘自網友的總結)

當在app內通過startActiviy啓動一個新的Activity的時候,主要會調用以下幾個函數

MyActivity.startActivity() 
Activity.startActivity() 
Activity.startActivityForResult 
Instrumentation.execStartActivty 
ActivityManagerNative.getDefault().startActivityAsUser() 

首選我們看一下startActivity方法

 @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }

startAcitity最終會執行startActivityForResult方法,如果調用startActivity方法傳入了-1,表示會有返回值返回。

繼續向下看startActivityForResult方法

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);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            if (requestCode >= 0) {
                mStartedActivity = true;
            }

            cancelInputsAndStartExitTransition(options);
        } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

在上面的代碼中,mParent進行了一個判Null操作,可以發現由於我們是第一次啓動Activity,所以這裏的mParent爲空,所以會執行if分之,然後調用mInstrumentation.execStartActivity方法,

重點看下以下代碼

nstrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);

mInstrumentation.execStartActivity中傳遞了幾個參數,第二個參數mMainThread就是程序的主線程,它在app啓動的時候創建的,即UI線程,mMainThread.getApplication()獲取到binder對象,代表了app的主線程;mToken也是一個Binder對象,代表了上一個Activity也通過Instumentation傳遞給AMS,此時AMS就知道誰向自己發送的消息了。

mInstrumentation的execStartActivity方法

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        Uri referrer = target != null ? target.onProvideReferrer() : null;
        if (referrer != null) {
            intent.putExtra(Intent.EXTRA_REFERRER, referrer);
        }
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    ActivityResult result = null;
                    if (am.ignoreMatchingSpecificIntents()) {
                        result = am.onStartActivity(intent);
                    }
                    if (result != null) {
                        am.mHits++;
                        return result;
                    } else if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        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;
    }

execStartActivity主要有以下幾個參數

who:啓動Activity對象

contextThread:Binder對象,爲主進程的context對象

token:Binder對象,

target:爲啓動的目標Activity

intent:啓動的Intent對象

requestCode:請求嗎

options:參數

通過,execStartActivity方法可以發現,該方法主要調用ActivityManager.getService()方法

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

//繼續看
    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

變量IActivityManagerSingleton是個Singleton對象,下面看下Singleton源碼

package android.util;

/**
 * Singleton helper class for lazily initialization.
 *
 * Modeled after frameworks/base/include/utils/Singleton.h
 *
 * @hide
 */
public abstract class Singleton<T> {
    private T mInstance;

    protected abstract T create();

    public final T get() {
        synchronized (this) {
            if (mInstance == null) {
                mInstance = create();
            }
            return mInstance;
        }
    }
}

 Singleton是一個抽象類,有一個抽象方法create()。有一個get()方法,內部通過單例模式創建T對象,調用create方法創建T對象,且只會創建一次T對象。

繼續查看create方法的具體實現,IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE)獲取一個關聯了系統服務ActivityManagerService的Binder對象;IActivityManager.Stub.asInterface(b)返回一個IActivityManager的代理對象,基於Binder機制,通過調用代理對象的方法,使得系統服務ActivityManagerService對應的方法被調用。可以猜測ActivityManagerService肯定繼承了IActivityManager.Stub,事實也確實如此。
       ActivityManagerService源碼如下:

public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
	
	//...code
	
    }

回到Instrumentation.execStartActivity方法的ActivityManager.getService().startActivity(...),就是IActivityManager的代理對象調用了startActivity方法,通過Binder機制,它會使系統服務ActivityManagerService的startActivity方法被調用。因此,啓動Activity的操作就交給了系統服務ActivityManagerService來處理了。

ApplicationThread繼承了IApplicationThread.Stub,並提出ApplicationThread重寫接口IApplicationThread的抽象方法在哪裏被調用。有意思的是,app.thread調用scheduleLaunchActivity方法,通過Binder機制,會使ApplicationThread$scheduleLaunchActivity方法被調用。
       於是,基於Binder機制,實現了一次進程間的通信,將啓動Activity的操作交給了ApplicationThread類。

 

ApplicationThread是ActivityThread的內部類,因此ApplicationThread可以調用外部類ActivityThread的方法,也可以這樣理解,啓動Activity的操作交給了ActivityThread來處理。

查看ActivityThread 的 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);

            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);
        }

創建了一個ActivityClientRecord對象,用於封裝啓動Activity需要的一些參數值。

最後一行調用ActivityThread$sendMessage方法,查看其源碼如下:

private void sendMessage(int what, Object obj) {
        sendMessage(what, obj, 0, 0, false);
}
 
//繼續查看
 
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
}

第19行,mH是一個H對象,類H是ActivityThread的內部類,並繼承了Handler。於是,啓動Activity的操作放在處理消息的方法H$handleMessage中。

private class H extends Handler {

    //...code
	public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
    	
	//...code

}

  第9行,取出Message對象中的obj字段,它是一個ActivityClientRecord對象;
       第10行,調用ActivityThread$getPackageInfoNoCheck方法,返回一個LoadedApk對象,並將該對象封裝到ActivityClientRecord的packgeInfo字段中。
       第11行,調用ActivityThread$handleLaunchActivity方法啓動Activity;

  查看ActivityThread$handleLaunchActivity源碼如下:

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

    Activity a = performLaunchActivity(r, customIntent);

    //...

    if (a != null) {
        //...

        handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
		    
        //...

    } else {
        // If there was an error, for any reason, tell the activity manager to stop us.
        try {
             ActivityManager.getService()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
    }

}

第4行,調用performLaunchActivity方法啓動Activity;
       第11行,若a不爲空,則調用handleResumeActivity方法,內部會調用Activity$onResume方法。具體的代碼流程還是比較好跟的,由於不是本篇的重點,有興趣的哥們可以自己去研究。
       第16行,當a爲空,也就是創建Activity的實例出錯了,走else語句。ActivityManager.getService()前面已經分析過了,返回IActivityManager的代理對象,調用該代理對象的方法,會向系統服務ActivityManagerService發送請求,基於Binder機制,最終會調用ActivityManagerService$finishActivity方法。
       也就是說,當創建Activity實例出錯後,停止啓動Activity的具體操作交給ActivityManagerService來處理。

 回到啓動Activity的流程,查看ActivityThread$performLaunchActivity源碼如下:

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");

        ActivityInfo aInfo = r.activityInfo;
        if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        }

        ComponentName component = r.intent.getComponent();
        if (component == null) {
            component = r.intent.resolveActivity(
                mInitialApplication.getPackageManager());
            r.intent.setComponent(component);
        }

        if (r.activityInfo.targetActivity != null) {
            component = new ComponentName(r.activityInfo.packageName,
                    r.activityInfo.targetActivity);
        }
ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        
	    //...code

            java.lang.ClassLoader cl = appContext.getClassLoader();
            if (appContext.getApplicationContext() instanceof Application) {
                activity = ((Application) appContext.getApplicationContext())
                        .instantiateActivity(cl, component.getClassName(), r.intent);
            }
            if (activity == null) {
                activity = mInstrumentation.newActivity(
                        cl, component.getClassName(), r.intent);
            }
            
	    //...code

            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

            //...code

            if (activity != null) {
                
		//...code
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);

                //...code

                mInstrumentation.callActivityOnCreate(activity, r.state);

		//...code
	     }
   
        return activity;
}

ActivityThread$performLaunchActivity方法的操作:
       1,獲取要啓動的Activity的ComponentName對象:裏面包含了包名,類名相關的信息;
       2,創建Activity的上下文環境:即創建了ContextImpl對象;
       3,創建Activity的實例:調用Instrumentation$newActivity方法,並使用類加載器創建Activity對象;
       4,創建Application對象;
       5,調用Activity$attach方法:初始化Activity類裏的一些數據;
       6,啓動Activity:調用Instrumentation$callActivityOnCreate方法;

 分析ActivityThread$performLaunchActivity方法:


       步驟2,創建了Activity的上下文環境,ContextImpl是抽象類Context的實現類,有關Context的操作的具體實現,大多數由ContextImpl完成。
       查看ActivityThread$createBaseContextForActivity源碼如下:

private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {

	//...code

	ContextImpl appContext = ContextImpl.createActivityContext(
                this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
	
	//...code

	return appContext;
}

繼續查看ContextImpl$createActivityContext源碼如下:

static ContextImpl createActivityContext(ActivityThread mainThread,
            LoadedApk packageInfo, ActivityInfo activityInfo, IBinder activityToken, int displayId,
            Configuration overrideConfiguration) {
	    //...code

	    ContextImpl context = new ContextImpl(null, mainThread, packageInfo, activityInfo.splitName,
                activityToken, null, 0, classLoader);
	    
	   //...code 
}

很顯然,最終創建了一個ContextImpl對象。

 

 步驟3,創建了一個Activity的實例。

        查看Instrumentation$newActivity源碼如下:

public Activity newActivity(ClassLoader cl, String className,
            Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        return (Activity)cl.loadClass(className).newInstance();
    }

通過ClassLoader創建Activity的實例。

 

       步驟4,創建了Application對象

       查看LoadedApk$makeApplication方法源碼如下:

public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        if (mApplication != null) {
            return mApplication;
        }

	Application app = null;

	//...

	app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
	
	//...

	mApplication = app;

	instrumentation.callApplicationOnCreate(app);
	//...

	return app;
}

 第3行,當mApplication不爲null時,也就是Application對象已經存在時,直接返回mApplication。很顯然Application是一個單例對象,一個應用程序中只存在一個Application對象。
       第11行,當應用程序內存中沒有Application對象時,創建一個Application對象。跟Activity一樣,都是通過類加載器ClassLoader來創建實例。具體代碼就不再展示,有興趣哥們可以去驗證。
       第16行,將Application對象app賦給字段mApplication。
       第18行,調用Application的onCreate方法。
       查看Instrumentation$callApplicationOnCreate方法源碼

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

 

步驟5,調用Activity$attach方法初始化數據。

       查看Activity$attach方法源碼:

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,
            Window window) {
        attachBaseContext(context);

        mFragments.attachHost(null /*parent*/);

        mWindow = new PhoneWindow(this, window);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
            mWindow.setSoftInputMode(info.softInputMode);
        }
        if (info.uiOptions != 0) {
            mWindow.setUiOptions(info.uiOptions);
        }
        mUiThread = Thread.currentThread();

        mMainThread = aThread;
        mInstrumentation = instr;
        mToken = token;
        mIdent = ident;
        mApplication = application;
        mIntent = intent;
        mReferrer = referrer;
        mComponent = intent.getComponent();
        mActivityInfo = info;
        mTitle = title;
        mParent = parent;
        mEmbeddedID = id;
        mLastNonConfigurationInstances = lastNonConfigurationInstances;
        if (voiceInteractor != null) {
            if (lastNonConfigurationInstances != null) {
                mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
            } else {
                mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
                        Looper.myLooper());
            }
        }

        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();
        mCurrentConfig = config;
    }

 第8行,參數context:步驟2中創建的ContextImpl對象傳入的。attachBaseContext方法:給ContextWrapper的成員變量mBase設置值爲ContextImpl對象。ContextWrapper是Context的一個子類,具體的代碼流程感興趣的哥們可以去驗證~
       第12行,創建了窗口對象PhoneWindow;
       第13~15行,給窗口對象註冊監聽接口;
       第23~37行,初始化一些變量的值;
       第47行,通過窗口Window創建WindowManagerImpl的實例;
       第54行,將47行創建的WindowManagerImpl的實例,設置給變量mWindowManager;

 

步驟6,調用Instrumentation$callActivityOnCreate方法啓動Activity。

       查看Instrumentation$callActivityOnCreate源碼:

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

 第3行,調用了Activity$performCreate方法。

       查看Activity$performCreate源碼如下

final void performCreate(Bundle icicle) {
        restoreHasCurrentPermissionRequest(icicle);
        onCreate(icicle);
        mActivityTransitionState.readState(icicle);
        performCreateCommon();
}

第3行,調用了Activity的onCreate方法啓動Activity,分析完成

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章