内容简介:Window(或者说View) 是怎么添加到 Android 系统中然后展示给用户的?让我们来探索一下 Window 的添加过程。要探索添加的过程,必须先在源代码中找到添加 Window 的入口方法。Window 的添加需要通过 WindowManager 的
Window 的添加过程
Window(或者说View) 是怎么添加到 Android 系统中然后展示给用户的?让我们来探索一下 Window 的添加过程。
Window 添加过程的入口方法
要探索添加的过程,必须先在源代码中找到添加 Window 的入口方法。
Window 的添加需要通过 WindowManager 的 addView
方法实现,但 WindowManager 是个接口,它的真正实现类是 WindowManagerImpl 类,但 WindowManagerImpl 也并没有直接实现对 Window 的添加、删除、更新操作,而是通过桥接模式将所有操作委托给 WindowManagerGlobal 去实现。最终会调用 WindowManagerGlobal 类的 addView
方法真正开启 View 的添加过程。
所有,Window 添加过程的真正入口方法实际上是 WindowManagerGlobal 类的 addView
方法。
Window 添加过程的主要流程
WindowManagerGlobal 的 addView
方法主要分为三大步:
-
检查参数 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"); } ... }
-
创建 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); ... }
-
通过 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
方法的源码,看它干了什么:@Override public void requestLayout() { if (!mHandlingLayoutInLayoutRequest) { checkThread(); mLayoutRequested = true; scheduleTraversals(); // scheduleTraversals 方法是View绘制的入口 } }
可以看到,是调用了
scheduleTraversals
方法进行绘制,我们知道scheduleTraversals
是 View 执行绘制过程的入口方法,该方法会经过测量、布局、绘制这三个过程把 View 绘制出来。 -
View 绘制出来以后是怎么通过IPC调用的方式添加到 Window 中的呢?
我们知道,WindowManager 是外界访问 Window 的入口,所以最终 WindowManager 会通过 IPC 的方式调用 WindowManagerService 的
addWindow
方法,这样一来, Window 的添加请求就交给了 WindowManagerService 来处理了,然后 WindowManagerService 会经过一系列的操作将 View 添加到 Window 中并展示出来。作为应用层开发者来说,了解到这个程度就差不多了,没必要去深究 WindowManagerService 的实现细节,至于 WindowManagerService 是如何处理 Window 的添加请求的,感兴趣的读者可以去查看源码。
-
参考书籍:
《Android 开发艺术探索》
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 主动模式和被动模式,添加监控主机,添加自定义模板,处理图像中的乱码,自动发现
- 苹果将为 Mac 添加 Face ID,为 Magic Keyboard 添加 Touch Bar
- android – 为什么AOSP添加新的API来支持库而不添加到SDK?
- [Framework] 添加系统服务
- go imports添加
- iOS动态添加属性
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Web Caching
Duane Wessels / O'Reilly Media, Inc. / 2001-6 / 39.95美元
On the World Wide Web, speed and efficiency are vital. Users have little patience for slow web pages, while network administrators want to make the most of their available bandwidth. A properly design......一起来看看 《Web Caching》 这本书的介绍吧!