從Android app說起

版權(quán)聲明:本文為博主原創(chuàng)文章譬淳,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接和本聲明薄啥。
本文鏈接:http://www.reibang.com/p/76f94c6452c0
先拋幾個(gè)問題
1:什么是Activity凤覆,它的作用是什么,我們一個(gè)android app看到的界面真的是Activity嗎蒲凶,如果不是,那是什么拆内。
2:我們經(jīng)承玻看到的Context,到處都是Context麸恍,服務(wù)都是通過它獲取的灵巧,它和Activity是什么關(guān)系。
3:看到的一些文章和帖子總是會(huì)說一個(gè)Activity會(huì)對(duì)應(yīng)一個(gè)PhoneWindow抹沪,那什么又是PhoneWindow刻肄,Activity和PhoneWindow的關(guān)系又是什么。
4:我們?cè)谧远x的Activity融欧,比如MainActivity的setContentView中設(shè)置了xml敏弃,最后就是我們看到的視圖,那么它和PhoneWindow和Activity又有什么關(guān)系噪馏。
5:有View和ViewGroup我們可以理解麦到,但是有時(shí)候又會(huì)看到一個(gè)ViewRootImpl和DecorView。它們又是什么關(guān)系欠肾,和Activity又是什么關(guān)系瓶颠。
6:Activity,Context刺桃,Application粹淋,DecorView,PhoneWindow虏肾,ActivityThread廓啊,以及ActivityManagerService欢搜,WindowsManagerService它們是如何構(gòu)建一個(gè)簡(jiǎn)單的helloworld android應(yīng)用的封豪。Application和Activity是誰先創(chuàng)建的,android應(yīng)用中為什么我們又不用繼承Application寫一個(gè)MyApplication類炒瘟。而如果寫了吹埠,它又有什么用。

先說一個(gè)場(chǎng)景,當(dāng)我們點(diǎn)擊手機(jī)桌面第一次運(yùn)行app的時(shí)候缘琅,Activity是如何啟動(dòng)的粘都。這個(gè)過程要說清楚其實(shí)還是比較復(fù)雜的,本篇中我們先跳躍式的從main函數(shù)開始運(yùn)行說起刷袍。main函數(shù)在ActivityThread類中翩隧,如下:

創(chuàng)建Activity或者說創(chuàng)建View


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

       Looper.prepareMainLooper();

       ActivityThread thread = new ActivityThread();
       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();

       throw new RuntimeException("Main thread loop unexpectedly exited");
   }

main函數(shù)中創(chuàng)建了Looper(關(guān)于Looper和Handler和Message在后續(xù)講)和ActivityThread,并且調(diào)用attach函數(shù)和ActivityManagerService關(guān)聯(lián)起來呻纹,為什么需要和ActivityManagerService關(guān)聯(lián)堆生,因?yàn)槲覀冎繟ctivity何時(shí)創(chuàng)建,管理都是ActivityManagerService管理的雷酪,所以就需要告訴ActivityManagerService我現(xiàn)在已經(jīng)運(yùn)行了main函數(shù)淑仆,以后有什么需要任務(wù)你就需要告訴我,而ActivityManagerService是怎么和應(yīng)用通信呢哥力,這就需要注意到attach中的這段代碼

private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            final IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
}

mgr.attachApplication(mAppThread),mgr是ActivityManagerService的client代理mAppThread是一個(gè)Binder對(duì)象蔗怠。

final ApplicationThread mAppThread = new ApplicationThread();

private class ApplicationThread extends ApplicationThreadNative {
// we use token to identify this activity without having to send the
        // activity itself back to the activity manager. (matters more with ipc)
        @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();
            updatePendingConfiguration(curConfig);

            sendMessage(H.LAUNCH_ACTIVITY, r);
        }
}

現(xiàn)在我們知道了,ActivityManagerService持有應(yīng)用的mAppThread對(duì)象吩跋,通過mAppThread服務(wù)端可以告應(yīng)用進(jìn)行啟動(dòng)Activity和其它的一些操作寞射,比方說調(diào)用scheduleLaunchActivity啟動(dòng)Activity。ActivityThread中有一個(gè)H類锌钮,它繼承Handler怠惶,ActivityManagerService調(diào)用應(yīng)用的操作最終通過H類發(fā)送消息,從Binder線程轉(zhuǎn)換到應(yīng)用進(jìn)程的主線程進(jìn)程完成轧粟。

private class H extends Handler {
        public static final int LAUNCH_ACTIVITY         = 100;
}

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

handleLaunchActivity中有一個(gè)performLaunchActivity調(diào)用策治,它會(huì)創(chuàng)建Activity(也就是new一個(gè)Activity),我們常常在Activity的onCreate函數(shù)中做一些初始化操作兰吟,到時(shí)我們好像很少寫Activity的構(gòu)造函數(shù)通惫,比如我們的MainActivity,我們其實(shí)也是可以寫它的構(gòu)造函數(shù)混蔼,并且可也在里面完成一些操作履腋,只是很少這樣做罷了。至此我們終于知道了Activity的創(chuàng)建了惭嚣。

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;

        if (r.profilerInfo != null) {
            mProfiler.setProfiler(r.profilerInfo);
            mProfiler.startProfiling();
        }

        // Make sure we are running with the most recent config.
        handleConfigurationChanged(null, null);

        if (localLOGV) Slog.v(
            TAG, "Handling launch of " + r);

        // Initialize before creating the activity
        WindowManagerGlobal.initialize();

        Activity a = performLaunchActivity(r, customIntent);
}

performLaunchActivity比較長(zhǎng)遵湖,我們截取部分關(guān)鍵代碼分析。part1:通過mInstrumentation的newActivity調(diào)用new出來我們的Activity晚吞,part2:創(chuàng)建了Activity之后會(huì)創(chuàng)建應(yīng)用的運(yùn)行Application上下文延旧,然后調(diào)用關(guān)鍵的attach函數(shù)

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//part1,通過mInstrumentation的newActivity調(diào)用new出來我們的Activity
Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }
//part2槽地,創(chuàng)建了Activity之后會(huì)創(chuàng)建應(yīng)用的運(yùn)行Application上下文迁沫,然后調(diào)用關(guān)鍵的attach函數(shù)
try {
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

            if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
            if (localLOGV) Slog.v(
                    TAG, r + ": app=" + app
                    + ", appName=" + app.getPackageName()
                    + ", pkg=" + r.packageInfo.getPackageName()
                    + ", comp=" + r.intent.getComponent().toShortString()
                    + ", dir=" + r.packageInfo.getAppDir());

            if (activity != null) {
                Context appContext = createBaseContextForActivity(r, activity);
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                if (r.overrideConfig != null) {
                    config.updateFrom(r.overrideConfig);
                }
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                        + r.activityInfo.name + " with config " + config);
                Window window = null;
                if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
                    window = r.mPendingRemoveWindow;
                    r.mPendingRemoveWindow = null;
                    r.mPendingRemoveWindowManager = 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, window);

//part3芦瘾,創(chuàng)建了Activity和attach之后,就調(diào)用到了我們熟悉的Activity的OnCreate
                activity.mCalled = false;
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
        }
}

創(chuàng)建了Activity之后集畅,在part2中會(huì)順帶著獲取到Application的對(duì)象近弟,代表著我們應(yīng)用的Application上下文,如果沒有挺智,就會(huì)創(chuàng)建祷愉。packageInfo是一個(gè)LoadedApk對(duì)象

public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        if (mApplication != null) {
            return mApplication;
        }
Application app = null;
        try {
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        }

if (instrumentation != null) {
            try {
                instrumentation.callApplicationOnCreate(app);//會(huì)調(diào)用Application的onCreate函數(shù)
            } catch (Exception e) {
            }
        }

至此我們明白了Application的創(chuàng)建和它的onCreate函數(shù)的調(diào)用過程∩馄模回調(diào)part2中的Activity的attach函數(shù)中來谣辞,它有一個(gè)參數(shù)就是Application。

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

終于看到PhoneWindow了沐扳,它就是在Activity的attach的時(shí)候創(chuàng)建出來的,這注意兩行關(guān)鍵代碼mWindow.setWindowControllerCallback(this)和mWindow.setCallback(this)泥从,因?yàn)锳ctivity繼承了Window的Callback,所以可以將Activity作為PhoneWindow的回調(diào)設(shè)置進(jìn)去,后面PhoneWindow接收到的消息和一些其它操作都是通過這個(gè)回調(diào)告訴Activity沪摄。
part3躯嫉,創(chuàng)建了Activity和attach之后,就調(diào)用到了我們熟悉的Activity的OnCreate

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

final void performCreate(Bundle icicle) {
        restoreHasCurrentPermissionRequest(icicle);
        onCreate(icicle);//onCreate中比如MainActivity繼承Activity杨拐,就調(diào)用到了MainActivity的onCreate函數(shù)
        mActivityTransitionState.readState(icicle);
        performCreateCommon();
    }

至此終于見到我們熟悉的Activity的onCreate和setContentView(R.layout.activity_main)函數(shù)了祈餐。setContentView在Activity中如下

public void setContentView(@LayoutRes int layoutResID) {
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
    }

getWindow()返回的是mWindow,就是在上面attach中創(chuàng)建的PhoneWindow哄陶,那么PhoneWindow的setContentView又做了什么呢帆阳。我們xml布局的視圖又是如何了呢。

public void setContentView(int layoutResID) {
        // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
        // decor, when theme attributes and the like are crystalized. Do not check the feature
        // before this happens.
        if (mContentParent == null) {
            installDecor();
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            mContentParent.removeAllViews();
        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene);
        } else {
            mLayoutInflater.inflate(layoutResID, mContentParent);
        }
    }

private void installDecor() {
mForceDecorInstall = false;
        if (mDecor == null) {
            mDecor = generateDecor(-1);
        } 
        if (mContentParent == null) {
                    mContentParent = generateLayout(mDecor);
        }
}

protected DecorView generateDecor(int featureId) {
        return new DecorView(context, featureId, this, getAttributes());
    }

到這里我們終于見到DecorView了屋吨,DecorView它是什么東西呢蜒谤,它是繼承FrameLayout的布局,也就是這里我們終于見到了View至扰,現(xiàn)在也明白了Activity的頂布局是DecorView了鳍徽,我們的xml布局中的View只是DecorView的Content布局內(nèi)容。

public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks {

但到目前為止我們僅僅只見到過Activity的創(chuàng)建和它OnCreate函數(shù)的運(yùn)行敢课,也知道了我們的xml視圖實(shí)例化之后加入到了DecorView中阶祭,這樣就顯示了視圖,如何接收onTouchEvent事件了嗎直秆,當(dāng)然不是濒募。這才是一部分,或者稱之為View視圖已經(jīng)準(zhǔn)備好了圾结,已經(jīng)創(chuàng)建了瑰剃,剩下就是如何顯示它們了。

顯示Activity或者說顯示View

回到開始的handleLaunchActivity疫稿,第一部分創(chuàng)建Activity或者說創(chuàng)建View也即運(yùn)行完performLaunchActivity函數(shù)之后培他,來到了handleResumeActivity函數(shù)鹃两,如下:

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

final void handleResumeActivity(IBinder token,
            boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
        ActivityClientRecord r = mActivities.get(token);
        if (!checkAndUpdateLifecycleSeq(seq, r, "resumeActivity")) {
            return;
        }
        r = performResumeActivity(token, clearHide, reason);

        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) {
                    a.mWindowAdded = true;
                    wm.addView(decor, l);
                }
}

其中的performResumeActivity會(huì)最終運(yùn)行到Activity的Resume函數(shù)遗座。但是這個(gè)時(shí)候其實(shí)我們的View是沒有顯示的舀凛,那Activity都Resume了View還沒有顯示,那是什么時(shí)候顯示呢途蒋,往下看注意這段代碼wm.addView(decor, l);decor是上文中的DecorView對(duì)象猛遍,wm是什么呢,ViewManager wm = a.getWindowManager()

public WindowManager getWindowManager() {
        return mWindowManager;
    }

那mWindowManager是什么實(shí)例呢号坡,它又是在什么地方創(chuàng)建或者賦值的,Activity的attach中有一行mWindowManager = mWindow.getWindowManager()懊烤,也就是說mWindowManager是獲取的PhoneWindow的對(duì)象。繼續(xù)往下跟Window類中有一個(gè)setWindowManager函數(shù)

public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
            boolean hardwareAccelerated) {
        mAppToken = appToken;
        mAppName = appName;
        mHardwareAccelerated = hardwareAccelerated
                || SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
        if (wm == null) {
            wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
        }
        mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
    }

PhoneWindow繼承Window宽堆,注意attach中有一段

mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);

也就是說mWindowManager是我們的mContext.getSystemService(Context.WINDOW_SERVICE)獲取到的WINDOW_SERVICE調(diào)用的createLocalWindowManager創(chuàng)建的WindowManagerImpl對(duì)象

public final class WindowManagerImpl implements WindowManager {
    //注意這個(gè)WindowManagerGlobal腌紧,它是一個(gè)單例對(duì)象,就是說一個(gè)進(jìn)程只有一個(gè)實(shí)例
    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
    public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
           return new WindowManagerImpl(mContext, parentWindow);
    }
}

mContext為Context對(duì)象畜隶,Context是一個(gè)抽象類壁肋,它的實(shí)現(xiàn)類是ContextImpl,查看ContextImpl的getSystemService函數(shù)籽慢,最終調(diào)用到了SystemServiceRegistry的getSystemService浸遗,而getSystemService返回的是它的HashMap SYSTEM_SERVICE_FETCHERS中保存的注冊(cè)的服務(wù),一下就是我們常用到的ActivityManager和WindowManager

@Override
    public Object getSystemService(String name) {
        return SystemServiceRegistry.getSystemService(this, name);
    }

final class SystemServiceRegistry {
    private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES =
            new HashMap<Class<?>, String>();
    private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
            new HashMap<String, ServiceFetcher<?>>();
    private static int sServiceCacheSize;

    // Not instantiable.
    private SystemServiceRegistry() { }

    static {
        registerService(Context.ACTIVITY_SERVICE, ActivityManager.class,
                new CachedServiceFetcher<ActivityManager>() {
            @Override
            public ActivityManager createService(ContextImpl ctx) {
                return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
            }});
        registerService(Context.WINDOW_SERVICE, WindowManager.class,
                new CachedServiceFetcher<WindowManager>() {
            @Override
            public WindowManager createService(ContextImpl ctx) {
                return new WindowManagerImpl(ctx);
            }});
}

回到handleResumeActivity中的wm.addView(decor, l);箱亿,也就是調(diào)用到了WindowManagerImpl的addView

@Override
    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
        mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
    }

最終調(diào)用到了WindowManagerGlobal中的addView跛锌,它里面又做了什么呢

public final class WindowManagerGlobal {
        private final ArrayList<View> mViews = new ArrayList<View>();
        private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
        public void addView(View view, ViewGroup.LayoutParams params,
                    Display display, Window parentWindow) {
                ViewRootImpl root;
                View panelParentView = null;

                synchronized (mLock) {
                    int index = findViewLocked(view, false);
                    root = new ViewRootImpl(view.getContext(), display);
                    view.setLayoutParams(wparams);

                    mViews.add(view);
                    mRoots.add(root);
                    mParams.add(wparams);
                }

                // do this last because it fires off messages to start doing things
                try {
                    root.setView(view, wparams, panelParentView);
                } catch (RuntimeException e) {
                }
         }
}

這里我們終于見到了ViewRootImpl。但是届惋,什么髓帽,做了這么多,就是看到new了一個(gè)ViewRootImpl對(duì)象脑豹,然后將View和new的ViewRootImpl對(duì)象分別add到mViews和mRoots列表中氢卡,說好的顯示View呢,怎么接收Event等呢晨缴。add就行了嗎?這個(gè)就要從ViewRootImpl的setView說起了译秦,說說ViewRootImpl了。

public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, ThreadedRenderer.HardwareDrawCallbacks {
public ViewRootImpl(Context context, Display display) {
        mContext = context;
        //代表WindowManagerService的WindowSession
        mWindowSession = WindowManagerGlobal.getWindowSession();
        mDisplay = display;
        mBasePackageName = context.getBasePackageName();
        mThread = Thread.currentThread();
        mWinFrame = new Rect();
        //代表WindowManagerService和ViewRootImpl通信的mWindow击碗,W對(duì)象
        mWindow = new W(this);
        mFirst = true; // true for the first time the view is added
        mAdded = false;
        //代表View和ViewRootImpl關(guān)聯(lián)的對(duì)象AttachInfo
        mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this);
        mFallbackEventHandler = new PhoneFallbackEventHandler(context);
        //我們常常說的編舞者對(duì)象Choreographer筑悴,控制UI刷新的,怎么做的1s內(nèi)刷新60HZ的
        mChoreographer = Choreographer.getInstance();
        mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
        loadSystemProperties();
    }
}

ViewRootImpl的構(gòu)造函數(shù)中的幾個(gè)關(guān)鍵對(duì)象都作了注釋 //代表WindowManagerService的WindowSession//代表WindowManagerService和ViewRootImpl通信的mWindow稍途,W對(duì)象//代表View和ViewRootImpl關(guān)聯(lián)的對(duì)象AttachInfo//我們常常說的編舞者對(duì)象Choreographer阁吝,控制UI刷新的,怎么做的1s內(nèi)刷新60HZ的械拍。
上文說的要從ViewRootImpl的setView說起突勇,setView怎么說呢装盯,代碼比較長(zhǎng),截取關(guān)鍵部分

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
        synchronized (this) {
            if (mView == null) {
                mView = view;

                mAttachInfo.mDisplayState = mDisplay.getState();
                mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);

                // If the application owns the surface, don't enable hardware acceleration
                if (mSurfaceHolder == null) {
                    enableHardwareAcceleration(attrs);//硬件加速初始化部分
                }
// Schedule the first layout -before- adding to the window
                // manager, to make sure we do the relayout before receiving
                // any other events from the system.
                requestLayout();
                if ((mWindowAttributes.inputFeatures
                        & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
                    mInputChannel = new InputChannel();
                }
                mForceDecorViewVisibility = (mWindowAttributes.privateFlags
                        & PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY) != 0;
                try {
                    mOrigWindowType = mWindowAttributes.type;
                    mAttachInfo.mRecomputeGlobalAttributes = true;
                    collectViewAttributes();
                    //mWindowSession添加窗口顯示甲馋,一個(gè)應(yīng)用只分配一個(gè)sWindowSession
                    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(),
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mOutsets, mInputChannel);
                } catch (RemoteException e) {
                }
              //mInputChannel埂奈,輸入通道,WindowInputEventReceiver定躏,輸入事件接收相關(guān)代碼
              if (mInputChannel != null) {
                    if (mInputQueueCallback != null) {
                        mInputQueue = new InputQueue();
                        mInputQueueCallback.onInputQueueCreated(mInputQueue);
                    }
                    mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
                            Looper.myLooper());
                }
}

setView中的enableHardwareAcceleration(attrs)是關(guān)于硬件加速的账磺,設(shè)計(jì)到View的
Draw問題,mWindowSession的addToDisplay是將視圖和窗口關(guān)聯(lián)的過程痊远。mInputChannel輸入通道垮抗,WindowInputEventReceiver接收輸入事件,有了這些一個(gè)app的完整的顯示碧聪,UI更新冒版,接收事件等終于準(zhǔn)備好了,剩下的就是點(diǎn)擊屏幕逞姿,事件如何傳遞到Activity和View的問題辞嗡,View如何將內(nèi)容顯示出來,并且不斷的進(jìn)行UI更新哼凯,這個(gè)就是Choreographer和Draw的問題欲间,而怎么Draw就涉及到硬件加速Draw和softDraw,本篇就先到這断部,下篇再講猎贴。
這里我們總結(jié)下ActivityThread接收到ActivityManagerService通過Binder調(diào)用,創(chuàng)建Activity的過程蝴光,這些過程是平時(shí)做應(yīng)用開發(fā)會(huì)有所涉及的她渴。

1:ActivityThread的mAppThread成員變量調(diào)用scheduleLaunchActivity成員函數(shù)準(zhǔn)備啟動(dòng)Activity,發(fā)送LAUNCH_ACTIVITY轉(zhuǎn)換給ActivityThread的H類對(duì)象mH處理(轉(zhuǎn)換到主線程處理)蔑祟。
2:mH對(duì)象接收到LAUNCH_ACTIVITY消息之后handleMessage調(diào)用handleRelaunchActivity成員函數(shù)趁耗,參數(shù)為ActivityClientRecord對(duì)象,表示記錄Activity的一些Client端信息疆虚,比如包名苛败,組件名稱等等。
3:handleLaunchActivity函數(shù)中調(diào)用performLaunchActivity径簿,執(zhí)行啟動(dòng)Activity罢屈。
   3.1:performLaunchActivity函數(shù)調(diào)用mInstrumentation new出需要啟動(dòng)的Activity,比如MainActivity
        3.1.1:new出Activity之后篇亭,通過調(diào)用LoadedApk的makeApplication缠捌,創(chuàng)建應(yīng)用的Application對(duì)象,同時(shí)創(chuàng)建Activity自己的Context
              3.1.2:這一切準(zhǔn)備好之后译蒂,調(diào)用Activity的attach函數(shù)曼月。
                     3.1.2.1:attach中主要?jiǎng)?chuàng)建了PhoneWindow對(duì)象谊却,作為Activity對(duì)應(yīng)的Window對(duì)象。
              3.1.3:Activity的attach運(yùn)行完成之后通過mInstrumentation調(diào)用Activity的OnCreate哑芹,調(diào)用到我們熟悉的OnCreate函數(shù)
                     3.1.3.1:OnCreate·函數(shù)中炎辨,調(diào)用setContentView。這時(shí)會(huì)new出Activity窗口的根布局DecorView同時(shí)將我們自己的xml布局實(shí)例化成View绩衷,并添加到DecorView根布局中蹦魔。
   3.2:handleResumeActivity函數(shù)運(yùn)行完成之后執(zhí)行handleResumeActivity激率,在handleResumeActivity函數(shù)中將DecorView加入到WindowManager中咳燕,
       在add DecorView的過程中創(chuàng)建了ViewRootImpl對(duì)象。ViewRootImpl對(duì)象完成UI Draw乒躺,消息接收等招盲,細(xì)節(jié)后續(xù)篇章講解。
4:進(jìn)入Looper消息循環(huán)嘉冒,等等消息輸入
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末曹货,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子讳推,更是在濱河造成了極大的恐慌顶籽,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件银觅,死亡現(xiàn)場(chǎng)離奇詭異礼饱,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)究驴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門镊绪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人洒忧,你說我怎么就攤上這事蝴韭。” “怎么了熙侍?”我有些...
    開封第一講書人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵榄鉴,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我蛉抓,道長(zhǎng)庆尘,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任芝雪,我火速辦了婚禮减余,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘惩系。我一直安慰自己位岔,他們只是感情好如筛,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著抒抬,像睡著了一般杨刨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上擦剑,一...
    開封第一講書人閱讀 49,821評(píng)論 1 290
  • 那天妖胀,我揣著相機(jī)與錄音,去河邊找鬼惠勒。 笑死赚抡,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的纠屋。 我是一名探鬼主播涂臣,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼售担!你這毒婦竟也來了赁遗?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤族铆,失蹤者是張志新(化名)和其女友劉穎岩四,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體哥攘,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡剖煌,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡进每,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出箩做,到底是詐尸還是另有隱情,我是刑警寧澤妥畏,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布邦邦,位于F島的核電站,受9級(jí)特大地震影響醉蚁,放射性物質(zhì)發(fā)生泄漏燃辖。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一网棍、第九天 我趴在偏房一處隱蔽的房頂上張望黔龟。 院中可真熱鬧,春花似錦、人聲如沸氏身。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蛋欣。三九已至航徙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間陷虎,已是汗流浹背到踏。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留尚猿,地道東北人窝稿。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像谊路,于是被迫代替她去往敵國(guó)和親讹躯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子菩彬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349