Android繪制源碼分析(上)

Android屏幕的框架
image.png
Activity與PhoneWindow與DecorView關(guān)系
image.png

Window

1.Windows是一個接口,實現(xiàn)它的是PhoneWindow

2.WindowManager創(chuàng)建一個window,WindowManager 為每一個window創(chuàng)建一個surface,并把該surface傳遞給應用以便應用在上面繪制,一個應用有很多Window。

3.Window是屏幕上用于繪制各種UI元素(比如Button,TextView)及響應用戶輸入事件(鍵盤事件)的一個矩形區(qū)域,它獨立繪制,不與其他界面產(chǎn)生影。

4.在Android系統(tǒng)中,每個Window是獨占一個Surface實例的顯示區(qū)域,每個窗口的Surface由WindowManagerService分配。
每個Window都對應著一個View和一個ViewRootImpl,Window和View通過ViewRootImpl來建立聯(lián)系,對于Activity來說,ViewRootImpl是連接WindowManager和DecorView的紐帶,繪制的入口是由ViewRootImpl的performTraversals方法來發(fā)起Measure,Layout,Draw等流程的

5.Window 是 Android 中窗口的宏觀定義,主要是管理 View 的創(chuàng)建,以及與 ViewRootImpl 的交互,將 Activity 與 View 解耦

DecorView

這個是根布局,包含了ActionBar,它就是我們看到的標題欄,另一個是ContentView(窗口內(nèi)容的容器),DecorView繼承了FragmentLayout,Activity生命周期的起點——onCreate回調(diào)方法里使用setContentView就是成了它的子View。每個Activity都與一個PhoneWindow相關(guān)聯(lián),用戶界面則由PhoneWindow所承載,

ActionBar
image.png
另一個是ContentView
image.png
ViewRootImpl

實現(xiàn)了ViewParent,對View的整個具體操作流程,是連接WindowManager和DecorView的紐帶

1.構(gòu)造方法
 public ViewRootImpl(Context context, Display display) {

        String processorOverrideName = context.getResources().getString(
                                    R.string.config_inputEventCompatProcessorOverrideClassName);
        if (processorOverrideName.isEmpty()) {
            // No compatibility processor override, using default.
            mInputCompatProcessor = new InputEventCompatProcessor(context);
        } else {
            InputEventCompatProcessor compatProcessor = null;
            try {
                final Class<? extends InputEventCompatProcessor> klass =
                        (Class<? extends InputEventCompatProcessor>) Class.forName(
                                processorOverrideName);
                compatProcessor = klass.getConstructor(Context.class).newInstance(context);
            } catch (Exception e) {
                Log.e(TAG, "Unable to create the InputEventCompatProcessor. ", e);
            } finally {
                mInputCompatProcessor = compatProcessor;
            }
        }

        if (!sCompatibilityDone) {
            sAlwaysAssignFocus = mTargetSdkVersion < Build.VERSION_CODES.P;

            sCompatibilityDone = true;
        }

        loadSystemProperties();
    }

2.在WindowManagerGlobal中實例化
    public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
        if (view == null) {
            throw new IllegalArgumentException("view must not be null");
        }
    
        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;

        ViewRootImpl root;
        View panelParentView = null;

            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) {
                // BadTokenException or InvalidDisplayException, clean up.
                if (index >= 0) {
                    removeViewLocked(index, true);
                }
                throw e;
            }
        }
    }
3.WindowManagerImpl中調(diào)用了addView
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();

 public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    applyDefaultToken(params);
    mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
4.PhoneWindow的setContentView()調(diào)用了步驟3
 public void setContentView(View view, ViewGroup.LayoutParams params) {
    // 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)) {
        view.setLayoutParams(params);
        final Scene newScene = new Scene(mContentParent, view);
        transitionTo(newScene);
    } else {
        mContentParent.addView(view, params);
    }
    mContentParent.requestApplyInsets();
    final Callback cb = getCallback();
    if (cb != null && !isDestroyed()) {
        cb.onContentChanged();
    }
    mContentParentExplicitlySet = true;
}
5.Activity的setContext()就是這個
public void setContentView(View view) {
    getWindow().setContentView(view);
    initWindowDecorActionBar();
}
總結(jié)1:由上面分析是連接WindowManager和DecorView的紐帶,Activity中的setContentView就是成了DecorView它的子View
6.WindowManagerImpl addView同時也在ScrollView調(diào)用
@Override
public void addView(View child) {
    if (getChildCount() > 0) {
        throw new IllegalStateException("ScrollView can host only one direct child");
    }

    super.addView(child);
}

總結(jié)2:ViewRootImpl管理DecorView的子類增改刪

WindowManager窗口管理

管理窗口的一些狀態(tài)屬性(view 的增加,刪除,窗口位置,更新等等),它管理window和WindowManagerService交互,由ViewRoot完成。主要的方法有:addview(),updateViewLayout();removeView()。
WindowManager是一個接口,WindowManagerImpl 是它的實現(xiàn)類。
WindowManager 里面維護了三個變量:mViews(根view),mRoots(viewroot),mParams(一些相關(guān)變量),由 WindowManagerGlobal 維護它們。

WindowManagerService

對系統(tǒng)中的所有窗口進行管理,它和WindowManager區(qū)別是WindowManager管理的是單獨的窗口,而WindowManagerService需要管理所有的窗口。

Android繪制源碼分析(中)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容