CallbackQueue负责存储 三种类型的事件,
public CallbackRecord extractDueCallbacksLocked(long now) { 取出Head节点,并删除多有比now小的时间节点,相当于有丢帧。
public void addCallbackLocked(long dueTime, Object action, Object token) {根据时间点从小到大排序,Head节点时间点最小。}
相关概念 驱动器 帧率刷新
Event驱动由以下来源组成。
- DisplayEventReceiver Display事件稳频器
- InputEventReceiver 顶层应用连接底层Touch、键盘硬件事件的唯一连接处
点击界面UI,更新界面,执行流程是
InputEventReceiver Native - 》 InputEventReceiver的dispatchInputEvent -》ViewRootImpl -》 Activity dispatchTouchEvent -》View performClick -》View invalidate() (requestLayout) --> ViewRootImpl scheduleTraversals ->Choreographer postCallback -> DisplayEventReceiver scheduleVsync -》 DisplayEventReceiver dispatchVsync - 》 Choreographer doFrame -》ViewRootImpl TraversalRunnable doTraversal -》 View measure layout draw 完成
每一次 DisplayEventReceiver scheduleVsync 只触发一次 DisplayEventReceiver dispatchVsync。
对于动画要获取持续的定时动力来源,就要循环调用scheduleVsync。但是
60hz计时由谁驱动的?
是由DisplayEventReceiver内部自己计算的,相当于稳频器,乱频的输入,进过DisplayEventReceiver后,输出为60hz的稳定频率。
相关核心调用路径如下:
doFrame
doTraversal
performTraversals
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
performLayout(lp, mWidth, mHeight);
performDraw();
ActivityThread performLaunchActivity ---> Activity.attach --> mWindow = new PhoneWindow(this, window);
--> PhoneWindow ( public PhoneWindow(Context context, Window preservedWindow) ) --> 【onCreate时才会调用】setContentView --> installDecor --> return new DecorView(context, featureId, this, getAttributes()); --> setWindow(window); =====(PhoneWindow.java)
handleResumeActivity --> wm.addView(decor, l); --> WindowManagerImpl mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow); --> WindowManagerGlobal root = new ViewRootImpl(view.getContext(), display); root.setView(view, wparams, panelParentView);
attch 有了PhoneWindow
setContentView 有了DecorView
onResume后 有了ViewRootImpl
root.setView(view, wparams, panelParentView);
ViewRootImpl
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
view.assignParent(this);