注:本文解析的源码基于 API 25,部分内容来自于《Android开发艺术探索》。
第一篇:《Window源码解析(一):与DecorView的那些事》
第二篇:《Window源码解析(二):Window的添加机制》
Header
在上一篇中,介绍了 Window 添加机制的实现。
那么今天就好好探究探究 Window 更新机制。其实 Window 的更新内部流程和添加 Window 并无什么差异,所以本篇可能会讲得比较简略。
但是还是值得我们去了解的,那么老死机开车了。
Window的更新机制
我们更新 Window 的代码:
WindowManager.updateViewLayout
WindowManagerImpl
updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params)
所以我们的入口就是 WindowManagerImpl 实现类的,先看代码:
1 | @Override |
果然,内部还是交给了 WindowManagerGlobal 来处理了,而且这代码和 addView
的极其类似。
WindowManagerGlobal
updateViewLayout(View view, ViewGroup.LayoutParams params)
1 | public void updateViewLayout(View view, ViewGroup.LayoutParams params) { |
这代码也基本上一看就懂的。因为是更新 Window ,所以肯定是要替换 params 了。
之后就是调用 ViewRootImpl.setLayoutParams
来设置新的 params 。
ViewRootImpl
setLayoutParams(WindowManager.LayoutParams attrs, boolean newView)
1 | void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) { |
在 setLayoutParams
中,调用了 scheduleTraversals()
方法。
在之前讲 View 工作原理的时候,我们都看过 scheduleTraversals()
最后会调用 performTraversals()
来开始 View 的测量、布局和绘制。所以在这,也就触发了 View 重新去调整自己。
performTraversals()
1 | private void performTraversals() { |
performTraversals()
方法太长了,其他的都不看了,我们只注意这一句代码。
接着,在内部又调用了 relayoutWindow(params, viewVisibility, insetsPending)
方法。一看这方法名就知道这方法都干什么了。
relayoutWindow()
1 | private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility, |
到了这一步,我们再次相遇熟悉的 mWindowSession
。
也知道了其实这是走了一个 IPC 的调用过程,在它内部肯定会利用 WindowManagerService 来完成 Window 的更新。
而 relayoutResult 就是这 IPC 最后返回的结果,也就是 Window 更新的结果。
虽然套路都懂了,但是有时候我们还是要吃。那么就去 Session 类中看看。
Session
relayout(IWindow window, int seq, WindowManager.LayoutParams attrs … )
1 | public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs, |
和我们预想的一样,内部是调用了 mService ,也就是 WindowManagerService 。
WindowManagerService
relayoutWindow(Session session, IWindow client, int seq, WindowManager.LayoutParams attrs … )
1 | public int relayoutWindow(Session session, IWindow client, int seq, |
WMS 的 relayoutWindow
方法中,先得到了需要更新的 WindowState 对象,接着去执行更新。如果 Window 的显示次序变化了的话,需要重新分配次序。最后就是设置一些 Window 更新完成后的一些变量了。
而其他的代码太复杂了,学艺不精,不能全部分析出来。
Footer
总之,Window 更新也和添加一样,都是通过 session 来调用 IPC 过程完成的。并且最终实现都是在 WindowManagerService 里。
至此,还有一篇 Window 删除还没分析。不用猜也知道,这流程肯定也是差不多的。但是我们还是要深入其中一探究竟。
今天就完结了,bye !