/** * Abstract base class for a top-level window look and behavior policy. An * instance of this class should be used as the top-level view added to the * window manager. It provides standard UI policies such as a background, title * area, default key processing, etc. * * <p>The only existing implementation of this abstract class is * android.view.PhoneWindow, which you should instantiate when needing a * Window. */ publicabstractclassWindow{ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) private WindowManager mWindowManager; @UnsupportedAppUsage private IBinder mAppToken; }
/** Interface to let you add and remove child views to an Activity. To get an instance * of this class, call {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}. */ publicinterfaceViewManager { publicvoidaddView(View view, ViewGroup.LayoutParams params); publicvoidupdateViewLayout(View view, ViewGroup.LayoutParams params); publicvoidremoveView(View view); }
/** * The interface that apps use to talk to the window manager. * </p><p> * Each window manager instance is bound to a particular {@link Display}. */ @SystemService(Context.WINDOW_SERVICE) publicinterfaceWindowManagerextendsViewManager{
/** * Provides low-level communication with the system window manager for * operations that are bound to a particular context, display or parent window. * Instances of this object are sensitive to the compatibility info associated * with the running application. * * This object implements the {@link ViewManager} interface, * allowing you to add any View subclass as a top-level window on the screen. * Additional window manager specific layout parameters are defined for * control over how windows are displayed. It also implements the {@link WindowManager} * interface, allowing you to control the displays attached to the device. * * <p>Applications will not normally use WindowManager directly, instead relying * on the higher-level facilities in {@link android.app.Activity} and * {@link android.app.Dialog}. * * <p>Even for low-level window manager access, it is almost never correct to use * this class. For example, {@link android.app.Activity#getWindowManager} * provides a window manager for adding windows that are associated with that * activity -- the window manager will not normally allow you to add arbitrary * windows that are not associated with an activity. * * @see WindowManager * @see WindowManagerGlobal * @hide */ publicfinalclassWindowManagerImplimplementsWindowManager{ @UnsupportedAppUsage privatefinal WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance(); privatefinal Window mParentWindow;
public WindowManagerImpl createLocalWindowManager(Window parentWindow){ returnnew WindowManagerImpl(mContext, parentWindow); }
public WindowManagerImpl createPresentationWindowManager(Context displayContext){ returnnew WindowManagerImpl(displayContext, mParentWindow); }
/** * Sets the window token to assign when none is specified by the client or * available from the parent window. * * @param token The default token to assign. */ publicvoidsetDefaultToken(IBinder token){ mDefaultToken = token; }
/** * Provides low-level communication with the system window manager for * operations that are not associated with any particular context. * * This class is only used internally to implement global functions where * the caller already knows the display and relevant compatibility information * for the operation. For most purposes, you should use {@link WindowManager} instead * since it is bound to a context. * * @see WindowManagerImpl * @hide */ publicfinalclassWindowManagerGlobal{
@UnsupportedAppUsage privatefinal ArrayList<View> mViews = new ArrayList<View>(); @UnsupportedAppUsage privatefinal ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>(); @UnsupportedAppUsage privatefinal ArrayList<WindowManager.LayoutParams> mParams = new ArrayList<WindowManager.LayoutParams>(); privatefinal ArraySet<View> mDyingViews = new ArraySet<View>(); }
// do this last because it fires off messages to start doing things try { root.setView(view, wparams, panelParentView, userId); } catch (RuntimeException e) {} }
最后,在沿着最后的逻辑,看看大名鼎鼎的 ViewRootImpl
ViewRootImpl
ViewParent
1 2 3 4 5 6 7 8 9 10 11 12 13
/** * Defines the responsibilities for a class that will be a parent of a View. * This is the API that a view sees when it wants to interact with its parent. * */ publicinterfaceViewParent{ /** * Called when something has changed which has invalidated the layout of a * child of this view parent. This will schedule a layout pass of the view * tree. */ publicvoidrequestLayout(); }
ViewRootImpl.java
1 2 3 4 5 6 7 8
/** * The top of a view hierarchy, implementing the needed protocol between View * and the WindowManager. This is for the most part an internal implementation * detail of {@link WindowManagerGlobal}. */ @SuppressWarnings({"EmptyCatchBlock", "PointlessBooleanExpression"}) publicfinalclassViewRootImplimplementsViewParent, View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks{}
setView
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
publicvoidsetView(View view, WindowManager.LayoutParams attrs, View panelParentView, int userId){ // Schedule the first layout -before- adding to the window // manager, to make sure we do the relayout before receiving // any other events from the system. requestLayout(); try { //... res = mWindowSession.addToDisplayAsUser(mWindow, mSeq, mWindowAttributes, getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrame, mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mAttachInfo.mDisplayCutout, inputChannel, mTempInsets, mTempControls); setFrame(mTmpFrame); } catch (RemoteException e) {} }
// Now let's make sure that the Window has installed its decor by retrieving it // 2.检查 window 是否已经创建 ,mWindow 赋值 ensureWindow(); // 3. 调用上面说的 getDecorView 创建 DecorView mWindow.getDecorView();
final LayoutInflater inflater = LayoutInflater.from(mContext); ViewGroup subDecor = null;
// 4. 根据 theme 配置信息,创建 subDecor 及
// subDecor 就是 DecorView 直接子 View,一般会包含 、、/// titleBar 等信息 // Now set the Window's content view with the decor // 5. 将 subDecor 添加到 mWindow 中,准确说是添加到 // DecorView 中。 mWindow.setContentView(subDecor);