Android window mechanism

Keywords: Windows Android Session

1. Familiar with window structure diagram:

2. Understanding PhoneWindow, DecorView, Windows Manager, ViewRootImpl and other keywords.

2.1 PhoneWindow

Every Activity has an instance of a Windows object, which is actually PhoneWindow type, so it can be seen that PhoneWindow is a subclass of Windows.

Knowledge: Every Activity has a PhoneWindow object. Phone Windows also has a Windows Manager for managing layouts and a DecorView for hosting layouts.

2.2 DecorView

DecorView inherits FrameLayout. DecorView contains two sub-Views: TitleView and ContentView. We usually set the layout in ContentView.

Knowledge: In Activity's onCreate() method, there is setContentView() method, which sets the layout in DecorView. It also needs to know that DecorView is the top level of view tree, and its function is to load the layout.

2.3 WindowManager

public interface WindowManager extends ViewManager {
    Display getDefaultDisplay();

    void removeViewImmediate(View var1);
    ......//ellipsis
}

It can be seen that Windows Manager inherits View Manager, so it can add, update and delete View, while Windows Manager Impl inherits Windows Manager with a member variable Windows Manager Global in Windows Manager Impl. The addView() method is executed to add the management window; therefore, Windows Manager is similar to a proxy and does not have a real management window, but manages the window through Windows Manager Global.

2.3.1 ViewManager

​public interface ViewManager{
    public void addView(View view, ViewGroup.LayoutParams params);
    public void updateViewLayout(View view, ViewGroup.LayoutParams params);
    public void removeView(View view);
}

As can be seen from the above code, there are three methods in ViewManager (add, update, remove): add, update, remove; using these three methods to manipulate views, that is to say, ViewManager is the interface used to add and remove View in activity.

2.3.2 WindowManagerImpl

​​public final class WindowManagerImpl implements WindowManager {
    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
    private final Display mDisplay;
    private final Window mParentWindow;

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

    .....//ellipsis

     @Override
    public void removeView(View view) {
        mGlobal.removeView(view, false);
    }
}

As can be seen from the above code, Windows Manager Impl inherits Windows Manager and defines a member variable mGlobal, which is a single object of type Windows Manager Global, which maintains the DecorView of all Windows in this application. MGlobal calls the addView() method to add and manage windows; therefore, Windows Manager does not really manage windows, but manages them through Windows Manager Global.

2.3.3 WindowManagerGlobal

​​​public final class WindowManagerGlobal {
    private static final String TAG = "WindowManager";
     public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
            ......//Ellipsis.
            root = new ViewRootImpl(view.getContext(), display);
            ......//ellipsis
            root.setView(view, wparams, panelParentView);
     }
}

As can be seen from the above code, the addView() method is called in Windows Manager Global, at which time the Windows Manager can manage DecorView. Then you can see an important object, ViewRootImpl (described below). It's easy to understand when you go back to Windows Manager after reading this.

Knowledge: Windows Manager is created when Activity executes attach(), and attach() method is called before onCreate(). Windows Manager implements the View Manager interface. Its ability to manage windows is actually achieved through Windows Manager Global. Windows Manager Global calls the addView() method, so that Windows Manager can manage DecorView, or Windows Manager can manage layout.

2.4.ViewRootImpl (replaced ViewRoot after Android 2.2)

​​​public final class WindowManagerGlobal {
    private static final String TAG = "WindowManager";
     public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
            ......//Ellipsis.
            root = new ViewRootImpl(view.getContext(), display);
            ......//ellipsis
            root.setView(view, wparams, panelParentView);
     }
}

As you can see above, ViewRootImpl initializes the ViewRootImpl after Windows Manager Global calls the addView() method. Continue to look at the setView() method in ViewRootImpl:

​public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
                ......//ellipsis
                requestLayout();
                ...//ellipsis
                try {
                ...//ellipsis
                    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(),
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mOutsets, mInputChannel);
               }
}

As you can see from the above code, we call the requestLayout() method and the mWindows Session. addToDisPlay() method. The following is addToDisPlay():

@Override
    public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
            int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
            Rect outOutsets, InputChannel outInputChannel) {
        return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
                outContentInsets, outStableInsets, outOutsets, outInputChannel);
    }

As you can see from the above code, there is an mService object, which is the Windows Manager Service, and mService executes the addWindow() method; that is to say, the layout is finally added by the Windows Manager Service. Looking back at the request Layout () method:

@Override
    public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
            checkThread();
            mLayoutRequested = true;
            scheduleTraversals();
        }
    }

As you can see from the above code, the checkThread() method is gone:

void checkThread() {
        if (mThread != Thread.currentThread()) {
            throw new CalledFromWrongThreadException(
                    "Only the original thread that created a view hierarchy can touch its views.");
        }
    }

As you can see from the above code, the checkThread() method makes a judgment, if it is not that the current thread will throw an exception (if the subthread updates the UI without using handler), after the checkThread() method is executed, go to the scheduleTraversals() method, and see this method below:

void scheduleTraversals() {
        if (!mTraversalScheduled) {
            ......//ellipsis
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
        }
    }

As you can see from the above code, the mTraversalRunnable interface is invoked asynchronously through handler in scheduleTraversals(). Choreographer's approach is not mentioned for the time being. Look down again:

final class TraversalRunnable implements Runnable {
        @Override
        public void run() {
            doTraversal();
        }
    }

As you can see from the above code, you have left the doTraversal() method and continue to look at the doTraversal() method:

  void doTraversal() {
            ......//ellipsis
            performTraversals();
    }

As you can see from the above code, you go through the performTraversals() method and continue to look at the performTraversals() method:

private void performTraversals() {  
        ......  //ellipsis
        performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
        ......  //ellipsis
        performLayout(lp, desiredWindowWidth, desiredWindowHeight);
        ......  //ellipsis
        performDraw();
        }
        ......  //ellipsis
    }

As can be seen from the above code, the method of measurement, layout and drawing is finally taken, and finally the measurement drawing is triggered. A View can be drawn through three processes: measure, layout and draw, so the drawing of View is done by ViewRootImpl.

Knowledge: ViewRootImpl is initialized when Windows Manager Global executes setView(), while ViewRootImpl executes setView() method to add views to windows through Windows Manager. ViewRootImpl can interact with Windows Manager Service of the system and manage the drawing and window state of DecorView. ViewRootImpl is not only a drawing function, but also an event distribution function.

Posted by The Stewart on Tue, 14 May 2019 03:48:42 -0700