文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Android布局控件View ViewRootImpl WindowManagerService关系

2023-02-10 12:01

关注

1. View,ViewRoot和WindowManager简单介绍

1.1 View和ViewGroup

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

1.2 ViewRootImpl

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

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.unscheduleTraversals();
                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 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;
        }
    }

前面注册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.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.mTraversalBarrier = this.mHandler.getLooper().getQueue().postSyncBarrier();
        this.mChoreographer.postCallback(2, this.mTraversalRunnable, (Object)null);
        if (!this.mUnbufferedInputDispatch) {
            this.scheduleConsumeBatchedInput();
        }
        this.notifyRendererOfFramePending();
        this.pokeDrawLockIfNeeded();
    }
}

scheduleTraversals是刷新方法的起点:

主线程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布局控件的资料请关注编程网其它相关文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯