Android's View system (B): DecorView create and display

DecorView is the top View, generally contains within it LinearLayout a vertical direction, in the vertical section 2 LinearLayout there, above the title bar, the following is the content column. Activity in the layout file we set by setContentView is actually loaded into the content field.

This article will describe how to create and DecorView is displayed.

Definitions: Unless otherwise specified herein, the corresponding source code analysis of api21.

Create a .DecorView

We mentioned above, DecorView is top View display, then ready to begin drawing View from DecorView. The start DecorView is familiar setContentView ().

   //代码片1 (Activity类)
   public void setContentView(int layoutResID) {
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
    }

After a review of discovery, getWindow () returns the Window class. And we know, Window is an abstract class, but it is the only PhoneWindow implementation class. In other words, want to know getWindow (). SetContentView (layoutResID), in fact, it is setContentView method PhoneWindow class.

//代码片2(PhoneWindow类)
@Override
    public void setContentView(int layoutResID) {
        // 1. 若mContentParent为空,创建一个DecroView
  		// mContentParent即为内容栏(content)对应的DecorView = FrameLayout子类
        if (mContentParent == null) {
            installDecor();      ---->分析1
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            // 若不为空,则删除其中的View
            mContentParent.removeAllViews();
        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene);
        } else {
            // 2. 为mContentParent添加子View
           // 即Activity中设置的布局文件
            mLayoutInflater.inflate(layoutResID, mContentParent);
        }
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
    }

We look at the code plate 2 analyzes a portion of (i.e., Line 7):

//代码片3(PhoneWindow类)
 private void installDecor() {
        if (mDecor == null) {
            //1. 通过赋值可以发现,mDecor就是DecorView。
            //  (DecorView的描述)This is the top-level view of the window, containing the window decor. 
            //  private DecorView mDecor;
            mDecor = generateDecor();   
            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
            mDecor.setIsRootNamespace(true);
            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
            }
        }
        if (mContentParent == null) {
            // 2.为DecorView设置布局格式 & 返回mContentParent ->>分析2
            mContentParent = generateLayout(mDecor);
//省略其他代码

Let's look at the code analysis part 2 of the sheet 3 (i.e., the first 16 lines of code):

//代码片4(PhoneWindow类)
**
  * 分析2generateLayout(mDecor)
  * 作用:为DecorView设置布局格式
  */
  protected ViewGroup generateLayout(DecorView decor) {

        // 1. 从主题文件中获取样式信息
        TypedArray a = getWindowStyle();

        // 2. 根据主题样式,加载窗口布局
        int layoutResource;
        int features = getLocalFeatures();

        // 3. 加载layoutResource
        View in = mLayoutInflater.inflate(layoutResource, null);

        // 4. 往DecorView中添加子View
        // 即文章开头介绍DecorView时提到的布局格式,那只是一个例子,根据主题样式不同,加载不同的布局。
        decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); 
        mContentRoot = (ViewGroup) in;

        // 5. 这里获取的是mContentParent = 即为内容栏(content)对应的DecorView = FrameLayout子类
        ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT); 
      
        return contentParent;
    }

Summary:
Here Insert Picture DescriptionIn this case, the top View (DecorView) was created to add layout files & Activity set. At this time, the top-level View (DecorView) still displayed, i.e. invisible.

Two .DecorView display

//代码片5(ActivityThread类)
final void handleResumeActivity(IBinder token,
            boolean clearHide, boolean isForward, boolean reallyResume) {

            ActivityClientRecord r = performResumeActivity(token, clearHide);

            if (r != null) {
                final Activity a = r.activity;
                  if (r.window == null && !a.mFinished && willBeVisible) {
                // 1. 获取Window实例中的Decor对象
                r.window = r.activity.getWindow();
                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;

                // 3. DecorView被添加进WindowManager了
                // 此时,还是不可见
                if (a.mVisibleFromClient) {
                    a.mWindowAdded = true;
                    
                    wm.addView(decor, l);
                }

                // 4. 此处设置DecorView对用户可见
                if (!r.activity.mFinished && willBeVisible
                    && r.activity.mDecor != null && !r.hideForNow) {
                     if (r.activity.mVisibleFromClient) {
                            r.activity.makeVisible();
                            // —>>分析3
                        }
                    }
            }

//代码片6(Activity类)
void makeVisible() {
   if (!mWindowAdded) {
            ViewManager wm = getWindowManager();
            // 1. 将DecorView添加到WindowManager ->>分析4
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        // 2. DecorView可见
        mDecor.setVisibility(View.VISIBLE);
    }

//代码片7(WindowManagerImpl类)
/**
  * 分析4:wm.addView
  * 作用:WindowManager = 1个接口,由WindowManagerImpl类实现
  */
  public final class WindowManagerImpl implements WindowManager {    
    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
    ...
    @Override
    public void addView(View view, ViewGroup.LayoutParams params) {
        mGlobal.addView(view, params, mDisplay, mParentWindow); ->>分析5
    }
}
//代码片8(WindowManagerGlobal类)
/**
  * 分析5:WindowManagerGlobal 的addView()
  */
  public void addView(View view, ViewGroup.LayoutParams params,Display display, Window parentWindow) {

             final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;

             ...

             synchronized (mLock) {

             // 1. 实例化一个ViewRootImpl对象
             ViewRootImpl root;
             root = new ViewRootImpl(view.getContext(), display);
             view.setLayoutParams(wparams);

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

             // 2. WindowManager将DecorView实例对象交给ViewRootImpl 绘制View
             try {
                  root.setView(view, wparams, panelParentView);   // ->> 分析6
                	}catch (RuntimeException e) {
               }
            }
 }

//代码片9(ViewRootImpl类)
**
  * 分析6:ViewRootImpl.setView()
  */
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
                requestLayout(); // ->>分析7
    }

//代码片10(ViewRootImpl类)
/**
  * 分析7:ViewRootImpl.requestLayout()
  */
    @Override
    public void requestLayout() {

        if (!mHandlingLayoutInLayoutRequest) {
        	// 1. 检查是否在主线程
            checkThread();
            mLayoutRequested = true;//mLayoutRequested 是否measure和layout布局。
            // 2. ->>分析8
            scheduleTraversals();
        }
    }
//代码片11(ViewRootImpl类)
/**
  * 分析8:ViewRootImpl.scheduleTraversals()
  */
    void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();

            // 通过mHandler.post()发送一个runnable,在run()方法中去处理绘制流程
            // 与ActivityThread的Handler消息传递机制相似
            // ->>分析9
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            ``````
        }
    }
//代码片12(ViewRootImpl类)
/**
  * 分析9:Runnable类的子类对象mTraversalRunnable
  * 作用:在run()方法中去处理绘制流程
  */
    final class TraversalRunnable implements Runnable {
        @Override
        public void run() {
            doTraversal(); // ->>分析10
        }
    }
//代码片13(ViewRootImpl类)
/**
    * 分析10:doTraversal()
    */
    void doTraversal() {
            mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);

            performTraversals(); 
            // 最终会调用performTraversals(),从而开始View绘制的3大流程:Measure、Layout、Draw
    }
    // 注:
    //    a. 我们知道ViewRootImpl中W类是Binder的Native端,用于接收WmS处理操作
    //    b. 因W类的接收方法是在线程池中的,故可通过Handler将事件处理切换到主线程中

The above process is as follows:
(1) adding objects to DecorView WindowManager in
(2) to create objects ViewRootImpl
(. 3) to the object WindowManager the DecorView ViewRootImpl objects
(4) ViewRootImpl object sends a message to trigger a traversal operation by the main thread Handler : performTraversals (); this method for performing a drawing process of View (measure, layout, draw)

Various changes ViewRootImpl call received object (e.g., the attribute change window from WmS dimensional change from control & tree redraw requests might initiator performTraversals () to complete the processing of the & therein.

As can be seen from:
(1) time and time again performTraversals () call to drive the control tree methodical work
(2) Once this method is not working properly, the entire control tree will be in a dead state
(3) Therefore performTraversals () can say object class is the core ViewRootImpl

The View is in drawing performTraversals () is executed. Three of the drawing process on View (measure, layout, draw) will come to learn later.

Published 81 original articles · won praise 37 · views 50000 +

Guess you like

Origin blog.csdn.net/gaolh89/article/details/104027903