Dialog dismiss 流程
来源:互联网 发布:java object to date 编辑:程序博客网 时间:2024/06/05 12:03
- Dialog.dismiss():
- 如果是在非UI线程调用,会将dismiss这个指令schedule到UI线程的handler来异步执行
- 否则同步执行。
- Dialog.dismissDialog()。
- WindowManagerImpl.removeViewImmediate(mDecor), mDecor在Dialog show()的时候调用mWindow.getDecorView()获得。
- WindowManagerGlobal.removeView(view, true): WindowManagerGlobal是进程级的单例,本进程内所有Window相关信息进行集中管理的结点,也包括了ViewRootImpl(Window的View树根节点)。
- 根据传入的view通过findViewLocked()在mViews**(维护了所有当前Window的DecorView)**中找到其所属Window对应的index.
- WindowManagerGlobal.removeViewLocked(int index, boolean immediate):
- 根据index获得Window的ViewRootImpl.
- 回调本进程的InputMethodManager的windowDismissed(mViews.get(index).getWindowToken())来告知输入法窗口某个Window即将dismiss,从而使得输入法窗口消失(finishInputLocked(), 如果当前输入法的servedView属于该Window的话)。
- 调用ViewRootImpl的die(immediate), 如果返回true, 代表die()没有被立刻执行,而是schedule(defer)到将来。
- 如果defer, 那么将此View加入到mDyingViews来保持追踪。
- ViewRootImpl.die(boolean immediate):
- 如果需要立刻执行(immediate == true)或者当前没有在进行Traversal(ViewRootImpl的一个操作,可以简单理解为对整个View树的measure+layout+draw)中,那么可以立即开始(doDie()), 进而返回false代表操作没有被defer.
- 否则schedule一个MSG_DIE来defer die()。
- ViewRootImpl.doDie():
- 如果已经dead(mRemoved == true), 不需要再死一次。
- 标记为dead(mRemoved = true)
- 如果该View之前被添加到了WMS中(mAdded = true), 调用dispatchDetachedFromWindow()来分发detach。
- dispatchDetachedFromWindow():
- 会回调其AttachInfo的ViewTreeObserver的dispatchOnWindowAttachedChange(false)
- 会回调ViewRootImpl承载的View(mView)的dispatchDetachedFromWindow将detach的消息分发到整个View tree。
- mView(DecorView)的parent设为null(assignParent(null))
- mView = null, 释放DecorView。
- 释放Surface(mSurface = null)。
- 调用mWindowSession.remove(mWindow)来将ViewRootImpl对应的Window从WMS中移除
- 释放InputChannel,不再接收input信息。
- unscheduleTraversals()取消之前schedule的Traversal任务(窗口都消失了,不再需要)。
- dispatchDetachedFromWindow():
- 如果添加到了WMS,但是还从来没有进行过Traversal(mFirst == false)
- invalidateDisplayLists()
- destroyHardwareRenderer()
- 下面的逻辑会判断mView != null, 不过在4.4的源码中,很奇怪,因为如果mAdded, 那么dispatchDetachedFromWindow()必然会将mView设置为null, 而这个判断进行的前提也是mAdded,即在进入这个判断中时,mView就一定是null了,mView != null的逻辑似乎永远不会进入到,因此这段逻辑不分析。
- 重置mAdded = false。
- WindowManagerGlobal.getInstance().doRemoveView(this), 告知WindowManagerGlobal该ViewRootImpl已经完成了自己的remove相关操作(WMS那边也已经知晓并开始remove了),后者会彻底消除ViewRootImpl在其内部的相关信息:包括在mRoots, mParams,mDyingViews中的信息.
- 至此,Window在本地Window体系中的信息基本都被清除了。
- Session: Session是每个ViewRootImpl和WMS通信的RPC节点
- remove(IWindow window)最终会RPC调到WMS的removeWindow(this, window)
- WMS.removeWindow(Session session, IWindow client):
- 通过windowForClientLocked(session, client, false)获取到Window对应的WindowState(win, 等于是该Window在WMS体系中的代理人和信息保存者).
- 为了多线程安全,会synchronized mWindowMap这个保存所有WindowState的map再向下执行。
- removeWindowLocked(session, win).
- WMS.removeWindowLocked(Session session, WindowState win)
- win.disposeInputChannel(), 注销对应的mInputChannel,不再接收input消息。
- 如果window之前是可见的,并且已经为其分配了Surface:
- 会安排一个合适的结束动画(WindowManagerPolicy.TRANSIT_EXIT/TRANSIT_PREVIEW_DONE)
- 使用window的WindowStateAnimator来驱动此动画(applyAnimationLocked().
- 如果确实发起了结束动画, 那么会将winState的mExiting设置为true.
- 并且设置win.mRemoveOnExit = true, win.mDisplayContent.layoutNeeded = true
- performLayoutAndPlaceSurfacesLocked()来开始动画。
- 结束函数,真正的remove会在动画结束以后进行。
- removeWindowInnerLocked(session, win):
- 如果之前window是可见的并且其消失会导致Configuration的变化(比如横屏变竖屏),那么会schedule一个H.SEND_NEW_CONFIGURATION来处理新的Configuration.
- updateFocusedWindowLocked, 让新的window获取焦点。
WMS.removeWindowInnerLocked(Session session, WindowState win):
- 遍历Window的ChildWindow,递归的对每个childWindow进行removeWindowInnerLocked.
- 如果当前输入法的target是此Window,那么显然需要为输入法找到下一个合适的target(moveInputMethodWindowsIfNeededLocked(false))
- 将window从PhoneWindowManager中移除(mPolicy.removeWindowLw(win))
- 调用WindowState的removeLocked()来让其完成自己内部的资源释放清理。
- 将相关信息从mWindowMap移除。
- windows/mPendingRemove/mResizingWindows中都移除此Window的相关信息。
- 释放window的相关token, (WindowToken, AppWindowToken)
- 如果当前WMS并不在layout过程中(mInLayout = false):
- assignLayersLocked(windows)根据最新的windows信息(删除了此window的)来重新为window分配layer。
- win.mDisplayContent.layoutNeeded = true, 表明此window所属的DispalyContent需要进行layout.
- performLayoutAndPlaceSurfacesLocked() 发起一次layout.
简单的总结下:
- Dialog的dismiss本质是其Window从WMS中被remove。
- Dialog的Window remove 流程和Activity的一致
- 某种意义上讲,Window体系有两套,本地(WindowManagerGloabl + WindowManagerImpl)和远端(Session + WMS)
- 本地Window体系负责维护本进程(一般是一个App)所有Window相关信息
- WMS则是整个系统的Window管理者和真正的操作执行者
- Window的remove要先在本地(WindowManagerGlobal以及WindowManagerImlp这一套本地的Window机制)执行/登记,然后再到远端(WMS,本地的remove触发了Session向远端发起请求)执行
0 0
- Dialog dismiss 流程
- dialog.dismiss()
- Dialog.hide() or Dialog.dismiss()?
- Dialog中的cancel和dismiss
- Android 自定义Dialog无法Dismiss
- dialog调用dismiss函数异常
- Dialog确认按钮不dismiss
- Dialog 的cancel 和dismiss 方法
- (转)什么时候调用Dialog的dismiss()方法
- dialog dismiss和cancle的区别
- Dialog调用dismiss方法出现异常解决方法
- Dialog.dismiss()方法无效的解决方法
- Android 反射应用---控制Dialog dismiss
- Dialog dismiss 和 cancel的区别
- android dialog dismiss cancel hide 的区别
- Android 开发 对话框Dialog dismiss和hide方法的区别
- Android 开发 对话框Dialog dismiss和hide方法的区别
- Dialog中cancel和dismiss的区别总结
- 访问单个节点的删除
- 手机数据恢复精灵教你快速找回误删除的手机通讯录
- FZU 2082 过路费(树链剖分+线段树)
- 购物车 全选逻辑
- LaTeX 工具使用介绍
- Dialog dismiss 流程
- 时间控件只显示年月
- JS基础第4课:prompt 消息对话框、打开新窗口(window.open
- <C++ Primer 5th 学习笔记>1
- sqlserver Job
- sturts2 POJO模式
- RxRetrofit 网络框架解析
- Oracel集合操作操作符:union(并运算),unionAll,intersect(交运算),minus(差运算)
- redis--集群--初步安装(转)