DecorView:創建與顯示

1、DecorView 創建
  1. 創建 PhoneWindow 對象。
  2. 爲 PhoneWindow 設置 WindowManager 對象。
  3. 爲 PhoneWindow 創建一個 DecorView 對象。
  4. 爲 DecorView 的 ContentView 設置 activity 中設置的佈局文件。
Activity.java
	
	    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, ActivityConfigCallback activityConfigCallback) {
        attachBaseContext(context);

        mFragments.attachHost(null /*parent*/);
        
		// 1.初始化 Window 對象。
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        // 2.設置回調,向 Activity 分發事件。
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
    	...
    	// 3.mWindow 設置 WindowManager 對象。
        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());
        }
        // 4.初始化 WindowManager 對象。
        mWindowManager = mWindow.getWindowManager();
    }
	
	// 設置 ContentView 佈局
    public void setContentView(@LayoutRes int layoutResID) {
    	// 爲 mWindow 設置佈局
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
    }
PhoneWindow.java
	// mWindow 設置佈局。
    @Override
    public void setContentView(int layoutResID) {
        // 1.mContentParent 爲 null,創建一個 DecorView。
        if (mContentParent == null) {
            installDecor();
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        	// 不爲 null,移除其中所有 View。
            mContentParent.removeAllViews();
        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene);
        } else {
        	// 2.爲 mContentParent 添加布局。
            mLayoutInflater.inflate(layoutResID, mContentParent);
        }
        mContentParent.requestApplyInsets();
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
        	// 3.回調通知,內容改變。
            cb.onContentChanged();
        }
        mContentParentExplicitlySet = true;
    }
    
	// 創建一個 DecorView
    private void installDecor() {
        mForceDecorInstall = false;
        if (mDecor == null) {
        	// 1.生成 DecorView。
            mDecor = generateDecor(-1);
            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
            mDecor.setIsRootNamespace(true);
            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
            }
        } else {
            mDecor.setWindow(this);
        }
        if (mContentParent == null) {
        	// 2.爲 DecorView 設置 mContentParent 佈局。
            mContentParent = generateLayout(mDecor);

            // Set up decor part of UI to ignore fitsSystemWindows if appropriate.
            mDecor.makeOptionalFitsSystemWindows();

            final DecorContentParent decorContentParent = (DecorContentParent) mDecor.findViewById(
                    R.id.decor_content_parent);
			。。。
    }

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

	// 生成 DecorView 的 mContentParent。
    protected ViewGroup generateLayout(DecorView decor) {
		
		// 1.獲取 Window 主題信息。
        TypedArray a = getWindowStyle();
		。。。
        // Inflate the window decor.
		// 2. 根據主題樣式,加載窗口布局。
        int layoutResource;
        int features = getLocalFeatures();
		。。。
		// 3.加載 layoutResource,往 DecorView 添加子 View。
        mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
		// 4.獲取 DecorView 的內容佈局 mContentParent 。
        ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
      	// ...設置 TitleView

        return contentParent;
    }
2、DecorView 顯示
  1. 啓動 Activity 後,主線程會調用 handleResumeActivity()。
  2. 將 DecorView 對象添加到 WindowManager。
  3. 創建 ViewRootImpl 對象。
  4. WindowManager 將 DecorView 交給 ViewRootImpl 對象。
  5. ViewRootImpl 通過 Handler 向主線程發送消息遍歷繪製視圖:performTraversals() 執行 View 的繪製流程。
ActivityThread.java

    final void handleResumeActivity(IBinder token,
            boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
      
        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();
                // 1.獲取 window 的 DecorView 對象。
                View decor = r.window.getDecorView();
                 // 2.DecorView 設置不可見。
                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) {
                    if (!a.mWindowAdded) {
                        a.mWindowAdded = true;
                        // 3.將 DecorView 添加到 WindowManager。
                        wm.addView(decor, l);
                    } else {
                        // The activity will get a callback for this {@link LayoutParams} change
                        // earlier. However, at that time the decor will not be set (this is set
                        // in this method), so no action will be taken. This call ensures the
                        // callback occurs with the decor set.
                        a.onWindowAttributesChanged(l);
                    }
                }

            // 4.設置 DecorView 可見。
            if (!r.activity.mFinished && willBeVisible
                    && r.activity.mDecor != null && !r.hideForNow) {
               。。。
                if (r.activity.mVisibleFromClient) {
                    r.activity.makeVisible();
                }
            }
 
            // Tell the activity manager we have resumed.
     
    }
Activity.java

    void makeVisible() {
        if (!mWindowAdded) {
            ViewManager wm = getWindowManager();
            // 1.將 DecorView 添加到 WindowManager。
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        // 2.設置 DecorView 可見。
        mDecor.setVisibility(View.VISIBLE);
    }
WindowManagerImpl.java

public final class WindowManagerImpl implements WindowManager {
    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();

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

}
WindowManagerGlobal.java

public final class WindowManagerGlobal {

    public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
		。。。
        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
       		 。。。
        	// 1.創建 ViewRootImpl 對象。
        	ViewRootImpl root;
            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 {
            	// 2.WindowManager 將 DecorView 對象交給 ViewRootImpl 繪製 View
                root.setView(view, wparams, panelParentView);
            } catch (RuntimeException e) {
                // BadTokenException or InvalidDisplayException, clean up.
                if (index >= 0) {
                    removeViewLocked(index, true);
                }
                throw e;
            }
        }
    }
    
}
ViewRootImpl.java

   public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
        synchronized (this) {
        requestLayout();
	}

    @Override
    public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
        	// 1.檢查是否在主線程。
            checkThread();
            // mLayoutRequested 表示是否 measure 和 layout 佈局。
            mLayoutRequested = true;
            scheduleTraversals();
        }
    }
    
    void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
            // 1.類似 Handler.post() 方法,mTraversalRunnable 處理繪製流程。
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            if (!mUnbufferedInputDispatch) {
                scheduleConsumeBatchedInput();
            }
            notifyRendererOfFramePending();
            pokeDrawLockIfNeeded();
        }
    }
    
    final class TraversalRunnable implements Runnable {
        @Override
        public void run() {
            doTraversal();
        }
    }
    final TraversalRunnable mTraversalRunnable = new TraversalRunnable();

    void doTraversal() {
        if (mTraversalScheduled) {
            mTraversalScheduled = false;
            mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);

            if (mProfile) {
                Debug.startMethodTracing("ViewAncestor");
            }
			// 1.開始 View 的3大流程:Measure、Layout、Draw。
            performTraversals();

            if (mProfile) {
                Debug.stopMethodTracing();
                mProfile = false;
            }
        }
    }
    
    // W 類爲 Binder 的 Native 端。用於接收 WMS 處理操作;W 類接收的方法是在線程池中,可以通過 Handler 將事件處理切換到主線程中。
   static class W extends IWindow.Stub {
   }
發佈了99 篇原創文章 · 獲贊 16 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章