开发者

Android布局控件View ViewRootImpl WindowManagerService关系

开发者 https://www.devze.com 2023-02-11 10:17 出处:网络 作者: One_Month
目录1. View,ViewRoot和WindowManager简单介绍1.1 View和ViewGroup1.2 ViewRootImpl1.3 WindowManager2. ViewRootImpl的起源2.1 ViewRootImpl创建时机2.2 ViewRootImpl通知注册Window3.ViewRootImpl与WindowManager
目录
  • 1. View,ViewRoot和WindowManager简单介绍
    • 1.1 View和ViewGroup
    • 1.2 ViewRootImpl
    • 1.3 WindowManager
  • 2. ViewRootImpl的起源
    • 2.1 ViewRootImpl创建时机
    • 2.2 ViewRootImpl通知注册Window
  • 3.ViewRootImpl与WindowManagerService的通信
    • 3.1 Windowsession
    • 3.2 IWindow
  • 4. ViewRootImpl与View

    1. View,ViewRoot和WindowManager简单介绍

    1.1 View和ViewGroup

    android的基本布局控件,结构是树装,ViewGroup实现了Viewparent接口,每个View内部保留一个ViewParent变量,代表他的父节点

    1.2 ViewRootImpl

    ViewRoot概念的具体实现类,也实现了ViewParent接口,每个View树顶级ViewParent就是这个类,主要管理

    • View树的measure,layout,draw
    • 向WindowManagerService注册Window
    • 接收WindowManagerService的事件回调

    1.3 WindowManager

    具体实现类WindowManagerImpl,不过最终任务委托给了WindowManagerGlobal对象,负责建立WindowManagerService连接和通信

    ViewRootImpl的功能相当于中介,左手掌握的顶级View,右手掌握WindowManger通信

    2. ViewRootImpl的起源

    2.1 ViewRootImpl创建时机

    这个和WindowManager是有点关联的,起点一般是Activity调用resume的时机,这个具体是在ActivityThread类中的

    public final class ActivityThread {
        final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
            if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                decor.setVisibility(4);
                wm = a.getWindowManager();
                LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = 1;
                l.softInputMode |= forwardBit;
                if (r.mPreserveWindow) {
                    a.mWindowAdded = true;
                    r.mPreserveWindow = false;
                    ViewRootImpl impl = decor.getViewRootImpl();
                    if (impl != null) {
                        impl.notifyChildRebuilt();
                    }
                }
                if (a.mVisibleFromClient) {
                    if (!a.mWindowAdded) {
                        a.mWindowAdded = true;
                        // 核心
                        wm.addView(decor, l);
                    } else {
                        a.onWindowAttributesChanged(l);
                    }
                }
            } else if (!willBeVisible) {
                r.hideForNow = true;
            }
        }
    }
    

    wm.addView()函数是入口,wm实际是WindowManager对象,WindowManager真正做工作的类是WindowManagerGlobal

    addView()实际上是添加的DecorView ,从r.window获取(Activity的话window实现类是PhoneWindow)

    public final class WindowManagerGlobal {
        public void addView(View view, android.view.ViewGroup.LayoutParams params, Display display, Window parentWindow) {
                    // 省略非必要代码
                    ViewRootImpl root = new ViewRootImpl(view.getContext(), display);
                    view.setLayoutParams(wparams);
                    this.mViews.add(view);
                    this.mRoots.add(root);
                    this.mParams.add(wparams);
                    try {
                        root.setView(view, wparams, panelParentView);
                    } catch (RuntimeException var13) {
                        if (index >= 0) {
                            this.removeViewLocked(index, true);
                        }
                        throw var13;
                    }
                }
            }
        }
    }
    

    这时候创建了ViewRootImpl对象,并把View,ViewRootImpl和windowManagerParam保存到WindowManagerGlobal的集合中,root.setView() 负责接力下一棒

    2.2 ViewRootImpl通知注册Window

    public final class ViewRootImpl implements ViewParent, Callbacks, DrawCallbacks {
    public void setView(View view, LayoutParams attrs, View panelParentView) {
        synchronized(this) {
            if (this.mView == null) {
                this.mView = view;
                // 省略代码
                try {
                    this.mOrigWindowType = this.mWindowAttributes.type;
                    this.mAttachInfo.mRecomputeGlobalAttributes = true;
                    this.collectViewAttributes();
                    /**
                    * 核心
                    */
                    res = this.mWindowSession.addToDisplay(this.mWindow, this.mSeq, this.mWindowAttributes, this.getHostVisibility(), this.mDisplay.getDisplayId(), this.mAttachInfo.mContentInsets, this.mAttachInfo.mStableInsets, this.mAttachInfo.mOutsets, this.mInputChannel);
                } catch (RemoteException var19) {
                    this.mAdded = false;
                    this.mView = null;
                    this.mAttachInfo.mRootView = null;
                    this.mInputChannel = null;
                    this.mFallbackEventHandler.setView((View)null);
                    this.unscheduljseTraversals();
                    this.setAccessibilityFocus((View)null, (AccessibilityNodeInfo)null);
                    throw new RuntimeException("Adding window failed", var19);
                } finally {
                    if (restore) {
                        attrs.restore();
                    }
                }
            }
        }
    }
    }
    

    ViewRootImpl保存和View对象,这里我们也可以发现 每一个顶级View都会对应一个ViewRootImpl对象,this.mWindowSession.addToDisplay() 通过WindowSession通知WindowManagerService注册Window

    3.ViewRootImpl与WindowManagerService的通信

    3.1 WindowSession

    ViewRootImpl向WindowManagerService发送信息的类,实际上是一个AIDL接口

    public interface IWindowSession extends IInterface {}
    

    ViewRootImpl通过WindowManagerGlobal.getWindowSession() 获取WindowSession对象

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

    前面注册Window的时候就用到的的就是WindowSession对象的addToDisplay

    3.2 IWindow

    这个也是一个AIDL接口文件,主要是用于WindowManagerService向ViewRootImpl发送消息,ViewRootImpl调用mWindowSession.addToDisplay注册窗口,会把IWindow这个信使带给WindowManagerService

    public final class ViewRootImpl implements ViewParent, Callbacks, DrawCallbacks {
        static class W extends android.view.IWindow.Stub {
            private final WeakReference<ViewRootImpl> mViewAncestor;
            private final IWindowSession mWindowSession;
            W(ViewRootImpl viewAncestor) {
                this.mViewAncestor = new WeakReference(viewAncestor);
                this开发者_Python学习.mWindowSession = viewAncestor.mWindowSession;
            }
            public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout, boolean alwaysConsumeNavbar, int displayId) {
               // 省略实现
            }
            public void moved(int newX, int newY) {
                // 省略实现
            }
            public void dispatchAppVisibility(boolean visible) {
                // 省略实现
            }
            public void dispatchGetNewSurface() {
                // 省略实现
            }
            public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) {
                // 省略实现
            }
            private static int checkCallingPermission(String permission) {
                // 省略实现
            }
            public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {
                // 省略实现
            }
            public void closeSystemDialogs(String reason) {
               // 省略实现
            }
            public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep, boolean sync) {
              // 省略实现
            }
            public void dispatchWallpaperCommand(String action, int x, int y, int z, Bundle extras, boolean sync) {
              // 省略实现
            }
            public void dispatchDragEvent(DragEvent event) {
              // 省略实现
            }
            public void updatePointerIcon(float x, float y) {
            // 省略实现
            }
            public void dispatchSystemUiVisibilityChanged(int seq, int globalVisibility, int localValue, int localChanges) {
                // 省略实现
            }
            public void dispatchWindowShown() {
                // 省略实现
            }
            public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) {
               // 省略实现
            }
            public void dispatchPointerCaptureChanged(boolean hasCapture) {
                // 省略实现
            }
        }
    }
    

    我们比较熟悉的可能就是WindowFocusChanged这个函数

    4. ViewRootImpl与View

    这两个关系紧密,我们最容易接触到的是ViewRootImpl控制者View的刷新

    void scheduleTraversals() {
        if (!this.mTraversalScheduled) {
            this.mTraversalScheduled = true;
            this.m编程客栈TraversalBarrier = this.mHandler.getLooper().getQueue().postSyncBarrier();
            this.mChoreographer.postCallback(2, this.mTraversalRunnable, (Object)null);
            if (!this.mUnbufferedInputDispatch) {
                this.scheduleConsumeBATchedInput();
            }
            this.notifyRendererOfFramePending();
            this.pokeDrawLockIfNeeded();
        }
    }
    

    scheduleTraversa编程客栈ls是刷新方法的起点:

    主线程Handler设置同步屏障(postSyncBarrier),让刷新任务先执行

    注册mChoreographer.postCallback()接收界面更新的同步消息

    接收到刷新的同步消息后,执行mTraversalRunnable的run方法,调用ViewRootImpl.doTraversal()

    void doTraversal() {
        if (this.mTraversalScheduled) {
            this.mTraversalScheduled = false;
            this.mHandler.getLooper().getQueue().removeSyncBarrier(this.mTraversalBarrier);
            if (this.mProfile) {
                Debug.startMethodTracing("ViewAncestor");
            }
            this.performTraversals();
            if (this.mProfile) {
                Debug.stopMethodTracing();
                this.mProfile = false;
            }
        }
    }
    

    this.performTraversals()内部调用performMeasure, performLayout, performDraw View树的measure,layout和draw实现刷新

    以上就是Android布局控件View ViewRootImpl WindowManagerService关系的详细内容,更多关于Android布局控件的资料请关注我们其它相关文章!

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    关注公众号