Window is an abstract class that is implemented PhoneWindow and created through WindowManager.

WindowManager is the entry point for the outside world to access the Window. The implementation of the Window is in WindowManagerService

The interaction between WindowManager and WindowManagerService is an IPC process

All views in Andorid are rendered through Windows

Be it an Activity, Dialog, or Taost

Therefore, Window is actually the direct manager of the View!!

1. The Windows and WindowManager

The process by which WindowManager adds a Window

Add a Button to the screen coordinates of (100,300). The Flags and type parameters are more important.

mFloatingButton = new Button(this);
mFloatingButton.setText("button");
mLayoutParams = new WindowManager.LayoutParams(
    LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 0 ,0 , PixelFormat.TRANSPARENT);
mLayoutParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL 
    | LayoutParams.FLAG_NOT_FOCUSABLE
    | LayoutParams.FLAG_SHOW_WHEN_LOCKED
    
mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
mLayoutParams.x = 100;
mLayoutParams.y =300;
mWindowManager.addView (mFloatignButton, mLayoutParams);
​
Copy the code

The Flags argument represents the properties of the Window

  • FLAG_NOT_FOCUSABLE

    This flag also enables FLAG_NOT_TOUCH_MODAL, and eventually events are passed directly to the Window at the lower level of the specific focus

  • FLAG_NOT_TOUCH_MODAL

    In this mode, click events outside the current Window region are passed to the underlying Window, and click events within the current Window region are handled by the system itself. This flag is important, and generally you need to turn it on, otherwise other Windows will not receive click events.

  • FLAG_SHOW_WHEN_LOCKED

    Enable this mode to display Windows on the lock screen.

The Type parameter indicates the Type of the Window, application Window, child Window, and system Window

  • The application Window corresponds to an Activity at levels 1-99
  • A child Window cannot exist on its own, but must be attached to a particular parent Window, hierarchy 1000-1999
  • System Windows are Windows that need to declare permissions when they can be created, such as Toast and the system status bar. These are system Windows, 2000-2999

    Use TYPE_SYSTEM_OVERLAY or TYPE_SYSTEM_ERROR

Note: Windows are hierarchical, each Window has a corresponding Z-ordered, and the higher-order ones are overwritten by the lower-order ones.

The functionality provided by Windows Manager is very simple, and there are only three common methods:

  • Add the View
  • Update the View
  • Delete the View

These three methods are defined in ViewManager, which Windows Manager inherits

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

Drag the Window effect

The position of the Window can be changed by setting the x and y values in LayoutParams based on the position of the fingers.

First to View Settings onTouchListener: mFloatingButton setOnTouchListener (this)

Then update the position of the View in the onTouch method.

public boolean onTouch(View v, MotionEvent envet){ int rawX = (int) event.getRawX(); int rawY = (int) event.getRwaY(); switch(event.getAction()){ case MotionEvent.ACTION_MOVE:{ mLayoutParams.x = rawX; mLayoutParams.y = rawY; MWindowManager. UpdateViewLayout (mFloatingButton mLayoutParams); break; } default: break; } return false; }Copy the code

2. Windows’ internal mechanism

A Window is an abstract concept; each Window corresponds to a View and a ViewRootImpl.

The Window and View are linked by View View PL, so the Window doesn’t actually exist, it exists as a View.

The View is the entity where the Window exists.

1. Add Windows

The Window is added through addView of WindowManager, an interface whose real implementation is the WindowManagerImpl class.

​
@Override
public void addView(View view, ViewGroup.LayoutParams params){
    mGlobal.addView(view, params , mDisplay, mParentWindow);
}
​
@Override
public void updateViewLayout(View view , ViewGroup.LayoutParams params){
    mGlobal.updateViewLayout(view ,params);
}
​
@Override
public void removeView(View view){
    mGlobal.removeView(view, false);
}
Copy the code

This is handled by Windows ManagerGlobal

Windows ManagerGlobal provides its own instances in the form of factories.

The Windows ManagerGlobal addView method is divided into the following steps

  1. Check that the parameters are valid, and adjust some layout parameters if they are child Windows

    if (view == null){ throw new IllegalArgumentException("view must not be null"); } if (display == null){ throw new IllegalArgumentException("display must be null"); } if(! (params instanceof WindowManager.LayoutParams)){ throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); } final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params; if (parentWindow ! = null){ parentWindow.adjustLayoutParamsForSubWindow(wparams); }Copy the code
  2. Create the ViewRootImpl and add the View to the list

There are several important lists inside Windows ManagerGlobal:

private final ArrayList<Viwe>mViews = new ArrayList<View>();
private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
private final ArrayList<WindowManager.LayoutParams> mParams = new ArrayList<WindowManager.LayoutParams>();
private final ArraySet<View> mDyingVies = new ArraySet<View>();
Copy the code
  • MViews stores views corresponding to all Windows
  • MRoots stores the view wrootimPL for all Windows
  • MParams stores layout parameters for all Windows
  • MDyingViews stores View objects that are being deleted. Or Window objects that have already called the removeView method but haven’t finished deleting yet.

Add a list of Window objects to the list in addView as follows

root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
​
mViews.add(view);
mRoot.add(root);
mParams.add(wparams);
Copy the code
  1. Update the interface and complete the Window addition process with the View wrootimpl

    This is done by the setView method of ViewRootImpl. The View drawing process is done by ViewRootImpl.

    SetView uses requestLayout internally to complete asynchronous refresh requests.

public void requestLayout(){ if (! mHandlingLayoutInLayoutRequest){ checkThread(); mLayoutRequested = true; // scheduleTraversals(); }}Copy the code

The Window is then finally added through WindowSession.

The mWindowSession type in the following code is IWindowSession, which is a Binder object. The actual implementation class is Session, i.e. the addition of Window is an IPC call

try{
    mOrigWindowType = mWindowAttributes.type;
    mAttachInfo.mRecomputeGlobalAttributes = true;
    collectViewAttributes();
    res =  mWindsSeesion.addToDisplay(mWindow, mSeq, mWindowAttributes, getHostVisibility(), mDisplay.getDisplayId(),mAttachInfo.mContentInsets, mInputChannel);
}catch (RemoteException e){
    mAdded = false;
    mView = null;
    mAttachInfo.mRootView = null;
    mInputChannel = null;
    mFallbackEventHandler.setView(null);
    unscheduleTraversals();
    setAccessibilityFocus(null, null);
    throw new RuntimeException("Adding window failed", e);
}
Copy the code

Windows are added inside the Session using WindowManagerService

public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
                       int viewVisibility, int displayId, Rect outCotentInsets, 
                       InputChannel outInputChannel){
    return mService.addWindow(this, window, seq, attrs, viewVisibility, disalayId, outContentInsets, outInputChannel);
}
Copy the code

This way, the Window’s add request is handled by WindowManagerService. A separate Session is reserved for each application within WindowManagerService.

2. Delete Windows

Windows ManagerImpl and then Windows ManagerGlobal.

public void removeView(View view , boolean immediate){ if (view == null){ throw new IllegalArgumentException("view must not be null"); } synchronized(mLock){int index = findViewLocked(View, true); View curView = mRoots.get(index).getView(); // Call removeViewLocked to further remove removeViewLocked(index, immediate); if (curView == view){ return; } throw new IllegalStateExceotion("Calling with view " + view + "but the ViewAncestor is attached to " + curView); }}Copy the code
private void removeViewLocked(int index, boolean immediate){ ViewRootImpl root = mRoots.get(index); View view = root.getView(); if (view ! = null){ InputMethodManager imm = InputMethodManager.getInstance(); if ( imm ! = null){ imm.windowDismissed(mViews.get(index).getWindowToken()); } } boolean deferred = root.die(immediate); if(view ! = null){ view.assignParent(null); if (deferred){ mDyingViews.add(view); }}}Copy the code

RemoveViewLocked is done with ViewRootImpl.

There are two delete interfaces available in Windows Manager: removeView and removeImmdiate

Indicates asynchronous deletion and synchronous deletion respectively

3. Windows update process

Implemented by the updateViewLayout method of Windows ManagerGlobal.

4. Create Windows

The Activity Window is created through a factory method of PolicyManager.

How the Activity view is attached to the Window, since the Activity view is provided by the setContentView method.

public void setContentView(int layoutResID){
    getWindow().setContentView(layoutResID);
    initWindowDecorActionBar();
}
Copy the code

As you can see here, the Activity hands off its implementation to the Window, whose implementation is PhoneWindow.

I’m going to focus on PhoneWindow

  1. If there is no DecorCView, create it

    DecorView is a FrameLayout, which is the top View in an Activity and typically contains a title bar and an inner bar.

    Anyway, the content bar must exist, and the content must have a specific id, which is “Content”. The full ID is Android.r.tent.

    DecorView creation is done by the installDecor method. Inside the method, generateDecor is used to create the DecorView directly, which is still a blank FrameLayout:

    protected DecorView generateDecor(){
        return new DecorView(getContext(), -1);
    }
    Copy the code

    To initialize the DecorView structure, PhoneWindow also needs to load the specific layout file into the DecorView via the generateLayout method.

    View in = mLayoutInflater.inflate(layoutResource, null);
    decor.addView(in , new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
    mContentRoot = (ViewGroup) in;
    ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
    Copy the code
/ / the id corresponding ViewGroup is mContentParent public static final ints ID_ANDROID_CONTENT = com. Android. Internal. R.i, dc ontentCopy the code
  1. Add the View to the mContentParent of the DecorView
// Add the Activity view directly to the mContentParent of the Decorview mLayOutInflater.inflate (layoutResID, MContentParent) // The Activity layout file is added to the DecorView's mContentParent, setContentViewCopy the code
  1. The onContentChanged method of the callback Activity notifies the Activity view that it has changed
final Callback cb = getCallback(); if (cb ! = null && ! isDestroyed()){ cb.onContentChanged(); }Copy the code

In the makeVisible method, the DecorView actually does the adding and displaying before the view of the Activity is visible to the user.

VoidmakeVisible () {if (! mWindowAdded){ ViewManager wm = getWindiowManager(); wm.addView(mDecor, getWindow().getAttributes()); mWindowAdded = true; } mDecor.setVisihility(View.VISIBLE); }Copy the code

In the makeVisible method, the DecorView actually does the adding and displaying before the view of the Activity is visible to the user.

VoidmakeVisible () {if (! mWindowAdded){ ViewManager wm = getWindiowManager(); wm.addView(mDecor, getWindow().getAttributes()); mWindowAdded = true; } mDecor.setVisihility(View.VISIBLE); }Copy the code

\