android P View框架3---ViewRootImpl

本秂侑毒 提交于 2020-02-26 14:50:03

本篇博客主要分析ViewTree的管理者ViewRoot即ViewRootImpl,是怎么工作的。

一,ViewRootImpl与WMS间的双向通信

ViewRootImpl > WMS:IwindowSession

WMS > ViewRootImpl:Iwindow

IwindowSession、Iwindow均是匿名的BindServer。

1. ViewRootImpl获取IWindowSession服务句柄的过程。

ViewRootImpl.java
public ViewRootImpl(Context context, Display display) {
        mContext = context;
        mWindowSession = WindowManagerGlobal.getWindowSession();
        ...
}


WindowManagerGlobal.java
    @UnsupportedAppUsage
    public static IWindowSession getWindowSession() {
        synchronized (WindowManagerGlobal.class) {
            if (sWindowSession == null) {
                try {
                    // Emulate the legacy behavior.  The global instance of InputMethodManager
                    // was instantiated here.
                    // TODO(b/116157766): Remove this hack after cleaning up @UnsupportedAppUsage
                    InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary();
                    IWindowManager windowManager = getWindowManagerService();
                    sWindowSession = windowManager.openSession(
                            new IWindowSessionCallback.Stub() {
                                @Override
                                public void onAnimatorScaleChanged(float scale) {
                                    ValueAnimator.setDurationScale(scale);
                                }
                            });
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
            return sWindowSession;
        }
    }

这里的IWindowManager是WindowManagerService在本地进程端的代理,windowManager的请求都是在远程端由WMS实现;

在ActivityThread中,处理handleResumeActivity时,也有一个WindowManager,即:ViewManager wm =a.getWindowManager();这里的wm是ViewManager,它是WindowManager类的基类,最终实现是WindowManagerImpl,是完全属于本地端的,存储与应用进程内部用于窗口管理的相关事务。

2.

在handleResumeActivity中,通过wm.addView(decor,l),最后会调用ViewRootImpl的setView,这个函数一方面把DecorView,也即是viewtree的根设置到ViewRootImpl中,用mView保存;另一方面会向WMS申请注册一个窗口,同时把mWindow对象(W类型,也是ViewRootImpl的内部类,是Iwindow服务端的实现)传给WMS,实现WMS跟Viewroot的通信。
 

ViewRootImpl.java
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
        synchronized (this) {
            if (mView == null) {
                mView = view;

                ...
                try {
                    mOrigWindowType = mWindowAttributes.type;
                    mAttachInfo.mRecomputeGlobalAttributes = true;
                    collectViewAttributes();
                    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(), mTmpFrame,
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel,
                            mTempInsets);
                    setFrame(mTmpFrame);
                } 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);
                } finally {
                    if (restore) {
                        attrs.restore();
                    }
                }

                ...
            }
        }
    }

跟窗口相关的两个概念,phoneWindow继承自Window类,是应用进程端对窗口的描述,表达了对窗口的一种约束;WMS中的window是一个抽象的概念,用WindowState来描述其状态,WindowState可以认为是WMS中对窗口的描述。

 

二,ViewRootImpl的工作方式

每个ViewTree只对应一个ViewRoot,它将跟WMS进行一系列的通信,包括窗口的注册、大小调整等。什么情况会执行这些操作?

1. ViewTree内部的请求,如view对象要更新UI,它会通过invalidate或者其他方式发起请求,随后这些请求会沿着ViewTree层层网上传递,最终到达ViewRoot,做为ViewTree的管理者它根据一系列实际情况来执行相应操作(如发起一次遍历、通知WMS等)。

2. 外部的状态更新,如WMS回调viewroot通知界面大小改变、触摸事件、按键事件等。

不管是内部请求、还是外部请求,viewroot通常会把这些消息入栈,然后ViewRootImpl中ViewRootHandler类来统一处理他们。ViewRootImpl是在WindowManagerImpl的addView的过程中创建的,addView调用的起点是ActivityThread的handleResumeActivity,所以说ViewRootImpl实际是运行在主线程中,ViewRootHandler实际上会跟主线程的消息队列挂钩。

内外部的请求都先入队到主线程的messagequeue,再有Viewroot具体处理。

ViewRootImpl.java

final class ViewRootHandler extends Handler {
    ...
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_INVALIDATE:
                    ((View) msg.obj).invalidate();
                    break;
                ...
            }
        }
    ...
}


 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!