读书笔记:理解 Android Window 的添加过程
来源:互联网 发布:网络诈骗安全用语 编辑:程序博客网 时间:2024/06/06 19:31
前言
我们知道,在 Windows 操作系统中,每一项任务都是在一个打开的窗口中进行的,窗口的概念非常好理解。而在 Android 中,其实窗口也是一个非常重要的概念,但是却很少被我们接触。
其实,和 Windows 操作系统一样,Android 中的每一个视图,例如一个 Activity、一个 Dialog 或者一个 Toast,它们都是一个窗口,这些窗口来自不同的进程,却全部由一个系统服务(WindowManagerService)统一管理。
我们也可以直接利用 WindowManager 来控制自己的 Window。
Window 的添加过程
WindowManager 有三个方法:
public void addView(View view, ViewGroup.LayoutParams params); public void updateViewLayout(View view, ViewGroup.LayoutParams params); public void removeView(View view);
这也是 WindowManager 提供的所有给开发者的方法,可以看到,这些方法都是直接操作 View 本身,而完全看不到 Window 的踪迹。其实,Window 是一个抽象的概念,具体的显示仍然是 View 的工作。
任何视图的显示都是通过 View,而任何 View 必须是依附于一个 Window,才能被显示。
一个 Window 包含着一个 View 和一个 ViewRootImpl,View 即需要被显示的 View 层次的根 View,而 ViewRootImpl 负责 Window 和 View 之间的沟通。
Window 被添加需要通过 WindowManager 的 addView 方法,而 WindowManager 是一个接口类,addView 真正的实现是在 WindowManagerImpl 中:
@Override public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow); } @Override public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { mGlobal.updateViewLayout(view, params); } @Override public void removeView(View view) { mGlobal.removeView(view, false); }
可以看到,WindowManagerImpl 又将所有操作委托给了 WindowManagerGlobal 来实现,WindowManagerGlobal 的 addView主要分为几个步骤:
1. 检查参数是否合法,如果 Window 类型是 SubWindow(1000-1999),则还需要调整一些参数
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)) { throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); } final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params; if (parentWindow != null) { parentWindow.adjustLayoutParamsForSubWindow(wparams); }
2. 创建 ViewRootImpl 并将 View 添加到列表中
因为 WindowManagerGlobal 管理的是整个系统的 Window,在 WindowManagerGlobal 中,维护着几个列表:
private final ArrayList<View> mViews = new ArrayList<View>(); private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>(); private final ArrayList<WindowManager.LayoutParams> mParams = new ArrayList<WindowManager.LayoutParams>(); private final ArraySet<View> mDyingViews = new ArraySet<View>();
其中,mView 对应着所有 Window 中的 View 层次的根 View,mRoots 对应着所有 Window 中的 ViewRootImpl,mParams 对应着所有 Window 中的布局参数,而 mDyingViews 保存了那些已经调用了 removeView 但还没删除的 View。
在 addView 接下来的步骤中,将要被添加的 Window 的 ViewRootImpl 被创建。
ViewRootImpl root; root = new ViewRootImpl(view.getContext(), display); view.setLayoutParams(wparams); mViews.add(view); mRoots.add(root); mParams.add(wparams);
3. 通过 ViewRootImpl 来更新界面,并完成 Window 的添加
addView 方法的最后,调用 ViewRootImpl 的 setView 方法
root.setView(view, wparams, panelParentView);
而在 setView 方法中,首先调用了 requestLayout() 方法
// 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();
@Override public void requestLayout() { if (!mHandlingLayoutInLayoutRequest) { checkThread(); mLayoutRequested = true; scheduleTraversals(); } }
这里的 scheduleTraversals 方法,其实就是 View 层级的整个测量、布局和绘制迭代过程的入口,也就是说,到这里此 Window 中的 View 层级的绘制过程已经开始。
在 setView 方法的最后,会通过 WindowSession 的 addToDisplay 方法,执行添加 Window 的最后一步:
try { mOrigWindowType = mWindowAttributes.type; mAttachInfo.mRecomputeGlobalAttributes = true; collectViewAttributes(); res = mWindowSession.addToDisplay( mSeq, mWindowAttributes, getHostVisibility(), mDisplay.getDisplayId(), mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mAttachInfo.mOutsets, mInputChannel );}
@Override public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets, Rect outOutsets, InputChannel outInputChannel) { // 最终将 Window 添加请求交给 WindowManagerService 处理了 return mService.addWindow( window, seq, viewVisibility, displayId, outStableInsets, outOutsets, outInputChannel ); }
这里的 WindowSession 是一个 IBinder 对象,连接系统进程 WindowManagerService,前面说过,WindowManagerService 管理整个 Android 系统的 Window,因此只有在 WindowManagerService 这里“登记”的 Window,才算是真正添加完成。进入 WindowManagerService 的 addWindow 方法中,可以看到大量的添加 Window 最终步骤的代码细节,至此,整个添加 Window 的大致流水帐就过了一遍。
Window 的 remove 和 update
Window 的 remove 和 update 和 add 操作相似,具体的顺序均为:
romove
WindowManager - > WindowManagerImpl -> WindowManagerGlobal -> ViewRootImpl .die() -> ViewRootImpl.dispatchDetchedFromWindow() -> WindowSession.removeWindow()
update
WindowManager - > WindowManagerImpl -> WindowManagerGlobal -> ViewRootImpl .setLayoutParams() -> ViewRootImpl.pokeDrawLockIfNeeded() -> WindowSession.pokeDrawLock(Window)
总结起来,Window 通过 ViewRootImpl 管理整个 View 层次,又总是最终通过 ViewRootImpl 调用 IBinder 对象 WindowSession 的方法,将最终步骤交付到 WindowManagerService 处。
- 读书笔记:理解 Android Window 的添加过程
- Android View添加到Window的过程
- Android解析WindowManager(三)Window的添加过程
- 理解Window和WindowManager(Android开发艺术探索读书笔记)
- Android开发艺术探索读书笔记-理解Window和WindowManager
- Android解析WindowManagerService(二)WMS的重要成员和Window的添加过程
- 读书笔记--理解Window和WindowManager
- Android Window理解(2)---应用窗口创建过程
- android中Activity、View、Window的理解
- Android Activity之Window的创建过程
- 【读书笔记】Android 应用程序进程的启动过程
- 读书笔记(8) 理解Window 和WindowManager
- 读书笔记-Android开发艺术探索-第8章-理解Window和WindowManager
- 源码 Window 的添加
- window.onload()的理解
- Android之Window、WindowManager(一):PopupWindow添加浮动窗口内部过程
- Android中Window添加View的底层原理
- 为android系统添加产品的过程
- ueditor使用小结
- 数据在OSI七层模型中的各层传输的数据和控制信息的格式总结
- 监督学习--统计三要素
- ZOJ 1148 The Game(bfs)
- Halcon学习笔记(一) 基础知识
- 读书笔记:理解 Android Window 的添加过程
- Handler实现倒计时并优化内存
- 从尾到头打印单向链表
- 基于安全的一些思考--缓冲区溢出
- java 代码邮件发送
- 海康威视2015年研发笔试题
- Problem D: 乌龟棋
- 耐人寻味的优化(数据结构)
- linux tr命令详解