了解WindowsManager

获取WindowsManager

WindowsManager可以通过getActivity().getWindowManager()来获取

/** Retrieve the window manager for showing custom windows. */
public WindowManager getWindowManager() {
    return mWindowManager;
}

WindowsManager是一个接口,那么他的实现类是什么呢?我们来找一下。

找到Activity的源码,发现WindowsManager对象是在Activity执行attach的时候缓存下来的,

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) {
            //省去若干代码
                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());
                }
                mWindowManager = mWindow.getWindowManager();
         }

可见,WindowsManager是通过context.getSystemService(Context.WINDOW_SERVICE),
​ mToken, mComponent.flattenToString(),
​ (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0)来获取的,

@Override
public Object getSystemService(String name) {
    return SystemServiceRegistry.getSystemService(this, name);
}

看一下SystemServiceRegistry的源码可以发现,WindowsManager是一个单例,在SystemServiceRegistry类被加载的时候存放到map里面的。

registerService(Context.WINDOW_SERVICE, WindowManager.class,
        new CachedServiceFetcher() {
    @Override
    public WindowManager createService(ContextImpl ctx) {
        return new WindowManagerImpl(ctx);
    }});

到这,就找的了WindowsManager的实现类WindowManagerImpl。

WindowManager如何工作的

接下来,我们看一下WindowManager是如何工作的。已经知道WindowManagerImpl是实现类了,我看看他的源码,来找一下是如何添加、更新、移除view的。

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);
}

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

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

会发现,WindowManagerImpl其实也不干活,而是一个桥接,添加、更新view的操作都交给mGlobal来做了。

public void addView(View view, ViewGroup.LayoutParams params,
        Display display, Window parentWindow) {
    //代码省略

    ViewRootImpl root;
    View panelParentView = null;

    synchronized (mLock) {
    //代码省略
        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 {
            root.setView(view, wparams, panelParentView);
        } catch (RuntimeException e) {
            // BadTokenException or InvalidDisplayException, clean up.
            if (index >= 0) {
                removeViewLocked(index, true);
            }
            throw e;
        }
    }
}

addview主要有四步:

1.构建ViewRootImpl

2.给view设置wparams

3.保存view、root、wparams到list里

4.调运ViewRootImpl的setView方法

ViewRootImpl本身并不是View,官方的解释是:

/**
 * 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}.
 */

ViewRootImpl是View视图结构的最顶层,ViewRootImpl是native与java层View系统通信的桥梁。

我们接着来看ViewRootImpl的setView方法

        synchronized (this) {
            if (mView == null) {
                mView = view;
               //代码省略
               int res; /* = WindowManagerImpl.ADD_OKAY; */

                // 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();
                if ((mWindowAttributes.inputFeatures
                        & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
                    mInputChannel = new InputChannel();
                }
                mForceDecorViewVisibility = (mWindowAttributes.privateFlags
                        & PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY) != 0;
                try {
                    mOrigWindowType = mWindowAttributes.type;
                    mAttachInfo.mRecomputeGlobalAttributes = true;
                    collectViewAttributes();
                    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(),
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mOutsets, mInputChannel);
                } catch (RemoteException e) {
                    //代码省略
                    throw new RuntimeException("Adding window failed", e);
                } finally {
                    if (restore) {
                        attrs.restore();
                    }
                }
            }
          //代码省略

        }

调运requestLayout()来请求布局,调运res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
​ getHostVisibility(), mDisplay.getDisplayId(),
​ mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
​ mAttachInfo.mOutsets, mInputChannel);

像WindowsManagerService发起显示当前mWindow的请求。

你可能感兴趣的:(了解WindowsManager)