Activity入門(二)

相關類

        與Activity相關的類有很多,彼此之間通過一些變量都可相互引用如下:

        從上圖可以看出,每個Activity實例中都含有一個DecorView對象,ViewRootImpl對象,以及WindowManager.LayoutParams對象()——它是DecorView對應的LayoutParams,三者之間的關聯由WMG維護(由於WMI完全委託給了WMG)。

attach()

        除構造函數,該方法是Activity中第一個被執行的方法。該方法內部會初始化一些Activity中的成員變量。如下:
        attachBaseContext(context);//會賦值到mBase成員變量。        
        mWindow = new PhoneWindow(this);
        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        mWindowManager = mWindow.getWindowManager();//這裏返回的是一個WindowManagerImpl對象
        第一個方法會將傳入的context保存到mBase成員變量中。
        從最後兩步可以看出,Activity與它所關聯的Window對象中的mWindowManager都是指向同一個WindowManageImpl對象。

startActivity()

        所有的startActivity()最終會走到ActivityThread#handleLaunchActivity()。
    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        //略
        Activity a = performLaunchActivity(r, customIntent);
        //創建Activity實例,並調用到attach(),onCreate(),onStart(),onRestoreInstanceState(),onPostCreate()
        if (a != null) {
            //略
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);
            //略
        } else {
            //略
        }
    }
performLaunchActivity。其主體代碼如下:
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);
        }
        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);
        }
    //上面是獲取待啓動activity的信息,並組裝成一個ComponentName對象。
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            //略
        } catch (Exception e) {
            //略
        }
    //在newActivity中,是通過反射拿到一個activity的實例對象的,這裏就創建了新的activity對象。
        try {
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);
       //makeApplication 反射拿application對象,如果已經存儲就直接返回。並調用Application#onCreate()方法。
            //略
            if (activity != null) {
                Context appContext = createBaseContextForActivity(r, 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);
               //略
                if (r.isPersistable()) {//調用到onCreate(),只不過前者調用的是onCreate(Bundle,PersistableBundle),後者調用的是onCreate(Bundle)
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                //略
                r.activity = activity;
                r.stopped = true;
                if (!r.activity.mFinished) {
                    activity.performStart();//調用Activity#onStart()
                    r.stopped = false;
                }
                if (!r.activity.mFinished) {//調用onRestoreInstanceState()
                    if (r.isPersistable()) {
                        if (r.state != null || r.persistentState != null) {
                            mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                    r.persistentState);
                        }
                    } else if (r.state != null) {
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                    }
                }
                //由上述兩個的判斷順序可以知道,onRestoreInstanceState()是在onStart()之後調用的,並且在有Bundle對象的時候才調用
                if (!r.activity.mFinished) {//調用Activity#onPostCreate()
                    activity.mCalled = false;
                    if (r.isPersistable()) {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state,
                                r.persistentState);
                    } else {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state);
                    }
                    //略
                }
            }
            r.paused = true;
            mActivities.put(r.token, r);
        } //略
        return activity;
    }
        在上述過程中通過createBaseContextForActivity()創建了一個Context對象,方法如下:
    private Context createBaseContextForActivity(ActivityClientRecord r,
            final Activity activity) {
        ContextImpl appContext = ContextImpl.createActivityContext(this, r.packageInfo, r.token);
        appContext.setOuterContext(activity);//這裏調用將傳入的Activity保存到mOuterContext變量中。
        Context baseContext = appContext;
	//略
        return baseContext;
    }
        我們可以發現在整個過程中,baseContext都是ContextImpl類型的。而該對象會傳遞到Activity#attach()中,並且最終被賦值到ContextWrapper#mBase(Activity也是間接繼承於ContextWrapper)屬性。
        而在第四行,將activity傳遞到了ContextImpl#mOuterContext屬性中。因此,在Activity可以通過mBase訪問到ContextImpl對象,在ContextImpl中可以通過mOuterContext訪問到它關聯的Activity對象。
        從這裏也可以看到,一個activity就有一個Context。

        經performLaunchActivity()執行完畢之後,得到了一個Activity實例,並調用了attach()->onCreate()->onStart()->onRestoreInstanceState()->onPostCreate()。但並沒有調用onResume()
        再回到handleLaunchActivity()中,調用完performLaunchActivity()之後,會調用handleResumeActivity()。如下:
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
        //略
        ActivityClientRecord r = performResumeActivity(token, clearHide);
        if (r != null) {
            final Activity a = r.activity;
            //略
            if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                ViewManager wm = a.getWindowManager();
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;
                if (a.mVisibleFromClient) {
                    a.mWindowAdded = true;
                    wm.addView(decor, l);
                }
                //略
}
        該方法中會調用performResumeActivity(),這裏又會調用Activity#performResume(),最終會在這裏通過Instrumentation調用onResume()。
        performResumeActivity()執行完畢之後,獲取了新建Activity的Window對象(在Activity#attach()中創建)以及DecorView(Activity#onCreate()中調用了setContentView()方法時創建),並將DecorView對象添加到Window中。
        通過WindowManager#addView()內部的一系列執行,最終會對View進行測量、佈局和顯示。這樣整個界面就顯示出來了。
整個過程:
        Activity#startActivity()->ActivityThread#handleLaunchActivity()->ActivityThread#performLaunchActivity()->Activity#attach()->Activity#onCreate()到Activity#onPostCreate()的生命週期->ActivityThread#handleResumeActivity()->ActivityThread#performResumeActivity()->Activity#onResume()->WindowManagerImpl#addView()->ViewRootImpl#setView()->ViewRootImpl#requestLayout()->ViewRootImpl#performTraversals()->ViewRootImpl#performMeasure()->ViewRootImpl#performLayout()->ViewRootImpl#performDraw()->Session#addToDisplay()->WindowManagerService#addWindow()到這一步,整個界面才展示出來。
        Activity的創建是在ActivityThread#performLaunchActivity()中完成的。
        與Activity關聯的PhoneWindow對象是在Activity#onCreate()中調用setContentView()時完成的,同時也完成了整個xml文件的解析與構建——View樹構建完畢,但未measure,layout與draw。
        ViewRootImpl#performMeasure(),performLayout,performDraw():執行view的measure,layout與draw的過程。
        WMS#addWindow()顯示整個Window,才顯示出具體的佈局。

setContentView

        基本上都在PhoneWindow中完成。



















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