Android有两个刷新函数,requestLayout和invalidate,invalidate只会引起View Hierarchy的draw过程,requestLayout会引起measure和layout过程,如果在layout过程中发现View的布局确实发生了改变,就会调用invalidate函数来刷新View
先来看以下View.requestLayout源码
- /**
- * Call this when something has changed which has invalidated the
- * layout of this view. This will schedule a layout pass of the view
- * tree.
- */
- public void requestLayout() {
- mPrivateFlags |= PFLAG_FORCE_LAYOUT;
- mPrivateFlags |= PFLAG_INVALIDATED;
- if (mParent != null && !mParent.isLayoutRequested()) {
- // 先上传递,最总到达顶层View即RootViewImpl
- mParent.requestLayout();
- }
- }
查看下ViewRootImpl.requestLayout源码
- public void requestLayout() {
- // 检测是否在UI线程
- checkThread();
- mLayoutRequested = true;
- // 重点
- scheduleTraversals();
- }
- public void scheduleTraversals() {
- if (!mTraversalScheduled) {
- mTraversalScheduled = true;
- //noinspection ConstantConditions
- if (ViewDebug.DEBUG_LATENCY && mLastTraversalFinishedTimeNanos != 0) {
- final long now = System.nanoTime();
- Log.d(TAG, "Latency: Scheduled traversal, it has been "
- + ((now - mLastTraversalFinishedTimeNanos) * 0.000001f)
- + "ms since the last traversal finished.");
- }
- // 发出一个遍历的Handler信息
- sendEmptyMessage(DO_TRAVERSAL);
- }
- }
RootViewImpl.handleMessage方法源码:
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- ......
- case DO_TRAVERSAL:
- if (mProfile) {
- Debug.startMethodTracing("ViewAncestor");
- }
- final long traversalStartTime;
- if (ViewDebug.DEBUG_LATENCY) {
- traversalStartTime = System.nanoTime();
- mLastDrawDurationNanos = 0;
- }
- // 接收到消息之后,开始执行遍历,具体measure,layout,draw操作
- performTraversals();
- if (ViewDebug.DEBUG_LATENCY) {
- long now = System.nanoTime();
- Log.d(TAG, "Latency: Spent "
- + ((now - traversalStartTime) * 0.000001f)
- + "ms in performTraversals(), with "
- + (mLastDrawDurationNanos * 0.000001f)
- + "ms of that time in draw()");
- mLastTraversalFinishedTimeNanos = now;
- }
- if (mProfile) {
- Debug.stopMethodTracing();
- mProfile = false;
- }
- break;
- ...
- }
- }