博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Window 的添加过程
阅读量:5903 次
发布时间:2019-06-19

本文共 3577 字,大约阅读时间需要 11 分钟。

Window 的添加过程

Window(或者说View) 是怎么添加到 Android 系统中然后展示给用户的?让我们来探索一下 Window 的添加过程。

Window 添加过程的入口方法

要探索添加的过程,必须先在源代码中找到添加 Window 的入口方法。

Window 的添加需要通过 WindowManager 的 addView 方法实现,但 WindowManager 是个接口,它的真正实现类是 WindowManagerImpl 类,但 WindowManagerImpl 也并没有直接实现对 Window 的添加、删除、更新操作,而是通过桥接模式将所有操作委托给 WindowManagerGlobal 去实现。最终会调用 WindowManagerGlobal 类的 addView 方法真正开启 View 的添加过程。

所有,Window 添加过程的真正入口方法实际上是 WindowManagerGlobal 类的 addView 方法。

Window 添加过程的主要流程

WindowManagerGlobal 的 addView 方法主要干了三件事:

  1. 检查参数 params 是否是 WindowManager.LayoutParams,如果不是说明参数不合法,则会抛出异常。

    public void addView(View view, ViewGroup.LayoutParams params,        Display display, Window parentWindow) {    if (view == null) {        throw new IllegalArgumentException("view must not be null");    }    if (display == null) {        throw new IllegalArgumentException("display must not be null");    }    if (!(params instanceof WindowManager.LayoutParams)) { // 检查 params 参数是否合法        throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");    }    ...}复制代码
  2. 创建 ViewRootImpl,并将 View 添加到列表中。

    public void addView(View view, ViewGroup.LayoutParams params,        Display display, Window parentWindow) {        ...		root = new ViewRootImpl(view.getContext(), display); // 创建 ViewRootImpl        view.setLayoutParams(wparams);        mViews.add(view); // 将View添加到mView列表中,mView 存储的是所有Window对应的View        mRoots.add(root);        mParams.add(wparams);        ...}复制代码
  3. 通过 ViewRootImpl 的 setView 方法来添加更新界面并通过 IPC 的方式调用 WindowManagerService 的 addWindow 方法完成 Window 的添加过程。

    public void addView(View view, ViewGroup.LayoutParams params,Display display, Window parentWindow) {		...        // do this last because it fires off messages to start doing things        try {             root.setView(view, wparams, panelParentView); // ViewRootImpl的setView 方法        } catch (RuntimeException e) {            // BadTokenException or InvalidDisplayException, clean up.            synchronized (mLock) {                final int index = findViewLocked(view, false);                if (index >= 0) {                    removeViewLocked(index, true);                }            }            throw e;        }}复制代码
    • ViewRootImpl 的setView 方法是如何实现界面的更新的呢?

      setView 方法中会调用 requestLayout() 方法去完成异步刷新请求:

      @SuppressWarnings({
      "EmptyCatchBlock", "PointlessBooleanExpression"})public final class ViewRootImpl implements ViewParent, View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks { private static final String TAG = "ViewRootImpl"; ... // 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(); } 复制代码

      我们再查看 requestLayout 方法的源码,看它干了什么:

      @Overridepublic void requestLayout() {    if (!mHandlingLayoutInLayoutRequest) {         checkThread();         mLayoutRequested = true;         scheduleTraversals(); // scheduleTraversals 方法是View绘制的入口    }}复制代码

      可以看到,是调用了 scheduleTraversals 方法进行绘制,scheduleTraversals 方法最终会调用 performTraversals 方法,我们知道 performTraversals 是 View 执行绘制过程的入口方法,该方法会经过测量、布局、绘制这三个过程把 View 绘制出来。

    • View 绘制出来以后是怎么通过IPC调用的方式添加到 Window 中的呢?

      我们知道,WindowManager 是外界访问 Window 的入口,所以最终 WindowManager 会通过 IPC 的方式调用 WindowManagerService 的 addWindow 方法,这样一来, Window 的添加请求就交给了 WindowManagerService 来处理了,然后 WindowManagerService 会经过一系列的操作将 View 添加到 Window 中并展示出来。

      作为应用层开发者来说,了解到这个程度个人觉得就可以了,没必要去深究 WindowManagerService 的实现细节,至于 WindowManagerService 是如何处理 Window 的添加请求的,感兴趣的读者可以去查看源码。

      参考书籍:《Android 开发艺术探索》

转载于:https://juejin.im/post/5c7f56c1f265da2db4144b5e

你可能感兴趣的文章
python基础教程_学习笔记19:标准库:一些最爱——集合、堆和双端队列
查看>>
javascript继承方式详解
查看>>
lnmp环境搭建
查看>>
自定义session扫描器精确控制session销毁时间--学习笔记
查看>>
PHP队列的实现
查看>>
单点登录加验证码例子
查看>>
[T-SQL]从变量与数据类型说起
查看>>
occActiveX - ActiveX with OpenCASCADE
查看>>
BeanUtils\DBUtils
查看>>
python模块--os模块
查看>>
Java 数组在内存中的结构
查看>>
《关爱码农成长计划》第一期报告
查看>>
学习进度表 04
查看>>
谈谈javascript中的prototype与继承
查看>>
时序约束优先级_Vivado工程经验与各种时序约束技巧分享
查看>>
minio 并发数_MinIO 参数解析与限制
查看>>
flash back mysql_mysqlbinlog flashback 使用最佳实践
查看>>
mysql存储引擎模式_MySQL存储引擎
查看>>
java 重写system.out_重写System.out.println(String x)方法
查看>>
配置ORACLE 11g绿色版客户端和PLSQL远程连接环境
查看>>