android view requestLayout,invalidate 事件的分发,接收,以及处理
2015-11-11 19:10
519 查看
handleResumeActivity
DecorView 是在ActivityThread 中的handleResumeActivity 通过mWindowManager 挂到 ViewRootImpl()上面去的。
所以所有的 view 的 requestLayout(),invalidate(),
都是通过 自身的parent.invalidate(),一步一步传递到最顶层的 DecorView,然后最后传递到ViewRootImpl里面。
这个事App process中的windowmanager中的一个成员变量
猜测应该是 每个acitivity 或者dialog都是一个window 要注册到这个里面去。
WindowManagerImpl 也变成了本地的代理。
在WindowManagerGlobal中 维护了这样一个 rootview 窗口的队列
private final ArrayList mViews = new ArrayList();
时刻保证 哪个窗口在最前面,点击事件传给谁。
他通过 openSession(),将自己和远端service绑定起来
WindowManagerGlobal 中
ViewRootImpl.java
public void setView()
这样子直接挂到了 windowmanagerService 上面注册,准备接受事件用,
什么touch事件啊 之类的都是通过windowmanagersetvice 中持有这个window的token 进行下发的。
扯远了 继续看 requestLayout();
在ViewRootImpl 中,
可以看到 不管是request 还是invalidate 都会 调用相同的代码scheduleTraversals();我们可以这么理解,就是说 layout和重绘都是在一次绘制过程中完成的,而不是两次。
在简单点描述就是 你在代码里面 前面请求requestLayout(),并且也请求了invalidate(),并不会产生两次 重绘。
在简单点来说,在一个msg循环里面,你多次请求requestLayout(),都是会被系统合并的。
它会在整个消息循环中加设一个栅栏,在接触此栅栏之前,后面的消息绝对不可能执行,其实就是为了,腾出cpu来 做layout draw事件
DecorView 是在ActivityThread 中的handleResumeActivity 通过mWindowManager 挂到 ViewRootImpl()上面去的。
所以所有的 view 的 requestLayout(),invalidate(),
都是通过 自身的parent.invalidate(),一步一步传递到最顶层的 DecorView,然后最后传递到ViewRootImpl里面。
这个事App process中的windowmanager中的一个成员变量
猜测应该是 每个acitivity 或者dialog都是一个window 要注册到这个里面去。
WindowManagerImpl 也变成了本地的代理。
在WindowManagerGlobal中 维护了这样一个 rootview 窗口的队列
private final ArrayList mViews = new ArrayList();
时刻保证 哪个窗口在最前面,点击事件传给谁。
他通过 openSession(),将自己和远端service绑定起来
WindowManagerGlobal 中
public void addView(View view, ViewGroup.LayoutParams params, 。。。。。 //rootImpl root.setView(view, wparams, panelParentView); 。。。。 }
ViewRootImpl.java
public void setView()
//通过rootImpl res = //mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes, getHostVisibility(), mDisplay.getDisplayId(), mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mInputChannel);
这样子直接挂到了 windowmanagerService 上面注册,准备接受事件用,
什么touch事件啊 之类的都是通过windowmanagersetvice 中持有这个window的token 进行下发的。
扯远了 继续看 requestLayout();
在ViewRootImpl 中,
@Override public void requestLayout() { if (!mHandlingLayoutInLayoutRequest) { checkThread(); mLayoutRequested = true; scheduleTraversals(); } } void invalidate() { mDirty.set(0, 0, mWidth, mHeight); if (!mWillDrawSoon) { scheduleTraversals(); } }
可以看到 不管是request 还是invalidate 都会 调用相同的代码scheduleTraversals();我们可以这么理解,就是说 layout和重绘都是在一次绘制过程中完成的,而不是两次。
在简单点描述就是 你在代码里面 前面请求requestLayout(),并且也请求了invalidate(),并不会产生两次 重绘。
在简单点来说,在一个msg循环里面,你多次请求requestLayout(),都是会被系统合并的。
void scheduleTraversals() { //如果已经在 重绘的过程中,这个请求会被忽略掉的。 if (!mTraversalScheduled) { mTraversalScheduled = true; //这个东西很厉害的,在messageQuene中会设置栅栏,涉及到垂直同步的问题。 mTraversalBarrier = mHandler.getLooper().postSyncBarrier(); //在mChoreographer会发出一个sync 的信号。 //并且在下个消息循环的时候 做doTraversal(),准备开始重新layout mChoreographer.postCallback( Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); if (!mUnbufferedInputDispatch) { scheduleConsumeBatchedInput(); } notifyRendererOfFramePending(); } }
它会在整个消息循环中加设一个栅栏,在接触此栅栏之前,后面的消息绝对不可能执行,其实就是为了,腾出cpu来 做layout draw事件
int enqueueSyncBarrier(long when) { }
相关文章推荐
- 优化UITableViewCell高度计算的那些事
- Ueditor绝对路径问题
- 如何让 UITableView 的 headerView跟随 cell一起滚动
- Builder模式
- LightOJ 1369 - Answering Queries(规律)
- iOS笔记UI--ipad分页控件
- UE4 Android Device Compatibility
- UE4.9 Hardware & Software Specifications
- Epic Games Shows Incredible New Anti-Aliasing Technique – Screenshots + Video Comparison
- UE4 iOS Packaged Game Size
- mysql中key 、primary key 、unique key 与index区别
- 自定义UITableViewCell
- hdoj 1530 Maximum Clique 【最大团】
- AnReplyCaliberQuery.js无端自动关闭,开启一段时间就自动关闭
- Maven实战之Quick Start
- 学习require.js中的一些总结
- SCRIPT5022: Sys.WebForms.PageRequestManagerServerErrorException: 输入字符串的格式不正确。
- UEFI+GPT浅析
- while continue 更新文件
- 移动端 UI 适配最佳实践(下)