从上面两篇SystemUI中发现StatusBar是通过WindowManager的addView()添加在界面上,那么内部Window是如何进行添加的?
带着疑问,跟踪到WindowManager.addView()方法中,由于WindowManager是一个接口,而实现它的是WindowManagerImpl.java
1 | public final class WindowManagerImpl implements WindowManager { |
在WindowManagerImpl可以发现,最终进行addView操作的是WindowManagerGlobal这个类,接着跟踪进去,可以发现重头戏在WindowManagerGlobal这个类中,那么接下来就开始理清内部逻辑。
1 | public void addView(View view, ViewGroup.LayoutParams params, |
在最开始280行-300行,对传进来的参数进行检查,view,display为null,params不属于WindomManager.LayoutParams都会抛出异常。另外如果是子Window,那么还需要通过adjustLayoutParamsForSubWindow(wparams)对布局参数进行调整。
在对参数进行检查后,首先通过findViewLocked查找到当前View的索引,并且判断当前view是否包含在mDyingViews(一个存储待删除的View的List集合)中,如果包含其中,则不等待MSG_DIE消息,直接调用doDie根据获取的索引进行删除。否则抛出异常。
在336处,如果是papanel window,则遍历所有View,获取papanel window所连接的view。准备工作已经做好,接下来就Window进行添加操作。
1 | root = new ViewRootImpl(view.getContext(), display); |
在上述代码的最后,通过ViewRootImpl.setView来更新界面.
1 | public final class ViewRootImpl implements ViewParent, |
758行,在setView方法中主要调用了mWindowSession的addToDisplay方法。mWindowSession属于IWindowSession类型,一个Binder对象,用于进行进程间通信,IWindowSession是Client端的代理,它的Server端的实现为Session,此前包含ViewRootImpl在内的代码逻辑都是运行在本地进程的,而Session的addToDisplay方法则运行在WMS所在的进程。
1 |
|
到了最后,可以发现addView其实是WindowManagerService进行addWindow操作。
Window的添加操作实际上是先通过WindowManagerGlobal对View进行第一步的处理,ViewRootImpl来进行界面的刷新,内部则通过Session与WindowManagerService进行跨进程通信,将添加的请求交给WindowManagerService来处理。