Android 源码解析之WindowManager更新窗口
来源:互联网 发布:git clone ssh 端口 编辑:程序博客网 时间:2024/06/10 04:31
一,写在前面
在阅读本篇文章前,建议先了解使用WindowManager添加窗口的内部实现原理,可以参考文章Android 源码解析之WindowManager添加窗口。本篇文章将从源码角度解析WindowManager更新窗口,也算是WindowManager添加,删除,更新窗口的完结篇。由于跟添加窗口比较类似,只会简单介绍下代码流程,不再重复介绍一些类,接口等。
二,WindowManager更新窗口
前面已经讲过,更新窗口实际上是调用WindowManagerImpl$updateViewLayout方法。
查看WindowManagerImpl$updateViewLayout源码如下:
@Override public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { applyDefaultToken(params); mGlobal.updateViewLayout(view, params); }
继续查看WindowManagerGlobal$updateViewLayout源码:
public void updateViewLayout(View view, ViewGroup.LayoutParams params) { if (view == null) { throw new IllegalArgumentException("view must not be null"); } if (!(params instanceof WindowManager.LayoutParams)) { throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); } final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params; view.setLayoutParams(wparams); synchronized (mLock) { int index = findViewLocked(view, true); ViewRootImpl root = mRoots.get(index); mParams.remove(index); mParams.add(index, wparams); root.setLayoutParams(wparams, false); } }首先对view,params做一些检查的操作;
第9行,params向下转型;
第11行,重新给View设置布局参数params;
第14行,获取View在集合中的索引位置;
第15行,根据索引位置index,获取mRoots集合中ViewRootImpl对象;
第16,17行,替换mParams集合中索引位置的WindowManager.LayoutParams对象;
第18行,调用ViewRootImpl$setLayoutParams方法,更新窗口;
上面分析有不能理解的地方,可阅读Android 源码解析之WindowManager添加窗口。
继续,查看ViewRootImpl$setLayoutParams源码如下:
void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) {//...codescheduleTraversals();}继续,查看ViewRootImpl$scheduleTraversals源码如下:
void scheduleTraversals() { if (!mTraversalScheduled) { mTraversalScheduled = true; mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier(); mChoreographer.postCallback( Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); if (!mUnbufferedInputDispatch) { scheduleConsumeBatchedInput(); } notifyRendererOfFramePending(); pokeDrawLockIfNeeded(); } }第7行,Choreographer调用postCallback方法,注册了TraversalRunnable接口。
查看ViewRootImpl$TraversalRunnable源码如下:
final class TraversalRunnable implements Runnable { @Override public void run() { doTraversal(); } }继续,查看ViewRootImpl$doTraversal源码:
void doTraversal() { if (mTraversalScheduled) { mTraversalScheduled = false; mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier); if (mProfile) { Debug.startMethodTracing("ViewAncestor"); } performTraversals(); if (mProfile) { Debug.stopMethodTracing(); mProfile = false; } } }第10行,调用performTraversals()。
继续,查看ViewRootImpl$performTraversals源码:
private void performTraversals() { //...coderelayoutResult = relayoutWindow(params, viewVisibility, insetsPending);//...code }继续,查看ViewRootImpl$relayoutWindow源码:
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility, boolean insetsPending) throws RemoteException {//...codeint relayoutResult = mWindowSession.relayout( mWindow, mSeq, params, (int) (mView.getMeasuredWidth() * appScale + 0.5f), (int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets, mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingMergedConfiguration, mSurface); //...code}mWindowSession是一个Session对象,获取该Session对象是一次IPC调用。基于Binder机制,完成了一次跟系统服务WindowManagerService的通信。(详细分析见文章Android 源码解析之WindowManager添加窗口)
查看Session$relayout源码如下:
@Override public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewFlags, int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets, Rect outStableInsets, Rect outsets, Rect outBackdropFrame, MergedConfiguration mergedConfiguration, Surface outSurface) { if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from " + Binder.getCallingPid()); Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag); int res = mService.relayoutWindow(this, window, seq, attrs, requestedWidth, requestedHeight, viewFlags, flags, outFrame, outOverscanInsets, outContentInsets, outVisibleInsets, outStableInsets, outsets, outBackdropFrame, mergedConfiguration, outSurface); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to " + Binder.getCallingPid()); return res; }第10行,mService是WindowManagerService对象,也就是说,更新窗口的操作最终交给了WindowManagerService来处理。
至于WindowManagerService更新窗口的流程就暂不介绍了,有兴趣的哥们可以参考老罗的博客。
三,总结
WindowManager添加窗口时,都用ViewRootImp$setView方法(见文章Android 源码解析之WindowManager添加窗口);
WindowManager删除窗口时,调用ViewRootImp$doDie方法(见文章Android 源码解析之WindowManager删除窗口);
WindowManager更新窗口时,调用ViewRootImp$setLayoutParams方法;
不管是添加,删除,更新窗口,都会通过Binder机制获取到Session对象。在Session类的内部,处理窗口的操作都是交给WindowManagerService来处理啦~
阅读全文
0 0
- Android 源码解析之WindowManager更新窗口
- Android 源码解析之WindowManager添加窗口
- Android 源码解析之WindowManager删除窗口
- android源码分析之windowmanager (android悬浮窗口的实现)
- Android 之 Window、WindowManager 与窗口管理
- Android 之 Window、WindowManager 与窗口管理
- Android 之 Window、WindowManager 与窗口管理
- Android 之 Window、WindowManager 与窗口管理
- Android 之 Window、WindowManager 与窗口管理
- Android之悬浮窗口实现(WindowManager)
- Android 之 Window、WindowManager 与窗口管理
- Android 之 Window、WindowManager 与窗口管理
- Android 之 Window、WindowManager 与窗口管理
- Android 之 Window、WindowManager 与窗口管理
- Android 之 Window、WindowManager 与窗口管理
- Android 之 Window、WindowManager 与窗口管理
- Android之悬浮窗口实现(WindowManager)
- Android 之 Window、WindowManager 与窗口管理
- 输入挂 等等总结
- JavaScript获取HTML元素的四种方法
- 毕业一年的菜鸟某东面试总结
- 数据库的隔离级别、事务的特性、范式
- UVA1589
- Android 源码解析之WindowManager更新窗口
- Recyclerview布局+spring上拉、下拉
- 新的开始
- jQuery判断用户名并实现省市的二级联动
- 使用jQuery动态创建一个表格,根据用户数输入的内容添加一行数据
- 面向对象编程初步
- 020 第五讲 特征值及特征向量
- 在C++中深拷贝和浅拷贝的基本用法
- 利用栈解决括号匹配和逆波兰表达式