android 屏幕刷新源码总结

view中所有invalidate()/requestLayout()等请求重绘的操作,最终都会表现在ViewRootImpl#performTraversals()中。
从invalidate()入手

invalidate() 
--> ViewRootImpl#scheduleTraversals()
--> ViewRootImpl#Choerographer.postCallback(TraversalsRunnable) // TraversalsRunnable封装了doTraversals()方法,doTraversal()方法又执行了performTraversals()方法。 performTraversals()方法会执行performMeasuer performLayout performDraw等操作,也就是重绘的基本操作。
--> Choerographer#postCallbackDelayed(TraversalsRunnable)
--> Choerographer#postCallbackDelayedInternal(TraversalsRunnable)
--> addCallbackLocked(TraversalsRunnable) // 将Runnable添加到CallbackQueue队列
--> Choerographer#scheduleFrameLocked() --> Choerographer#scheduleVsyncLocked // 添加到队列后,继续请求监听Vsync信号
--> DisplayEventReceiver#nativeScheduleVsyncLocked()

通过以上的代码逻辑,就把view的invalidate()(实际是performTraversals())请求封装到了Runnable中,并加入到CallbackQueue队列中等待执行。同时,因为有重绘操作,所以向底层(SurfaceFlinger)请求监听下一次的Vsync信号。 好让请求的重绘操作执行。

==============================================================
底层发出Vsync信号时的刷新过程:

SurfaceFlinger.Vsync 
--> DisplayEventReceiver.dispatchVsync
--> FrameDisplayEventReceiver.onSync & run
--> Choreographer.doFrame()
--> Choreographer.doCallbacks()
--> Choreograpger.extraDueCallbackLocked() //去除之前存放的Runnable并执行

1、ViewRootImplViewRootImpl怎来的,大家可以看看ActivityThread里面的handleResumeActivity,抛开anr这些系统的窗口等,理论上一个APP应该是一个ViewRootImpl在WindowManagerGlobal的addView会

root = new ViewRootImpl(view.getContext(), display);       
root.setView(view, wparams, panelParentView);

也就是说, ViewRootImpl的mView其实是DecorView.而DecorView是一个activity中最外层的view了,其实是继承的FrameLayout。
而对于View不论是Invalidate还是requestlayout,这些重绘开始的地方都是ViewRootImpl的scheduleTraversals,在scheduleTraversals中,

mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL,mTraversalRunnable, null);

有这样一行代码,这个mTraversalRunnable就是调用了View measure,layout,draw的非常经典的performTraversals方法。
而postCallback中做的事情主要就是根据时间看这个啥时候执行,如果要立即执行了就添加到一个callback队列中然后去请求VSYNC(这里只考虑有VSYNC的场景)。如果不需要立即执行就sendmessage做一个队列排队去。
Choreographer是对VSYNC做了监听的,当有VSYNC消息的时候会执行onVsync,最终走到Choreographer的doFrame,在这里会将从callback队列中取出runnable进行绘制。
所以对于当用户手动去invalidate,或者requestlayout的情况,还是会通过Choreographer对这些请求做排队处理,所有绘制的地方都会等待VSYNC的消息回调再去做相应的绘制。所以就不会出现,用户要求去绘制,但是这个时机和VSYNC不同步的问题了。

android 屏幕刷新源码总结_第1张图片

你可能感兴趣的:(Android开发)