内容简介: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动态添加属性
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
风吹江南之互联网金融
陈宇(江南愤青) / 东方出版社 / 2014-6-1 / 55元
随着中国互联网金融浪潮高涨,P2P、众筹、余额宝、微信支付等新生事物层出不穷,加之大数据等时髦概念助阵,简直是乱花渐欲迷人眼,令媒体兴奋,公众狂热。那么,互联网金融真的能“颠覆”传统金融吗?当互联网思维对撞传统金融观念,是互联网金融的一统天下,还是传统金融业的自我革新?究竟是谁动了金融业的奶酪? 本书作者早期试水创立具有互联网金融雏形的网站,后来成为互联网金融的资深投资人,基于其多年在该领域......一起来看看 《风吹江南之互联网金融》 这本书的介绍吧!