Android图形系统(十一)-Choreographer

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android图形系统(十一)-Choreographer相关的知识,希望对你有一定的参考价值。

参考技术A android4.1之后增加了Choreographer机制,用于同Vsync机制配合,统一动画、输入和绘制时机。本文以绘制为例来简单学习下Choreographer。

ViewRootImpl的requestLayout开启绘制流程:

这里主要关注两点:

postSyncBarrier : Handler 的同步屏障。它的作用是可以拦截 Looper 对同步消息的获取和分发,加入同步屏障之后,Looper 只会获取和处理异步消息,如果没有异步消息那么就会进入阻塞状态。也就是说,对View绘制渲染的处理操作可以优先处理(设置为异步消息)。

Choreographer : 编舞者。统一动画、输入和绘制时机。也是这章需要重点分析的内容。

frameworks\base\core\java\android\view\Choreographer.java

每一个Looper线程都有自己的Choreographer,其他线程发送的回调只能运行在对应Choreographer所属的Looper线程上

Choreographer类中有一个Looper和一个FrameHandler变量。变量USE_VSYNC用于表示系统是否是用了Vsync同步机制,该值是通过读取系统属性debug.choreographer.vsync来获取的。如果系统使用了Vsync同步机制,则创建一个FrameDisplayEventReceiver对象用于请求并接收Vsync事件,最后Choreographer创建了一个大小为3的CallbackQueue队列数组,用于保存不同类型的Callback。

这里,不同类型的Callback包括如下4种:

CallbackQueue是一个容量为4的数组,每一个元素作为头指针,引出对应类型的链表,4种事件就是通过这4个链表来维护的。

而FrameHandler中主要处理三类消息:

Choreographer提供了两类添加回调的方式:postCallback 与 postFrameCallback,当然对应类型也包含delay的方法,算上其实有4个方法。

postCallback对应的:

postFrameCallback对应的:

相比之下postCallback更灵活一点。两者最终都会调到:postCallbackDelayedInternal

mCallbackQueues先把对应的callback添加到链表上来,然后判断是否有延迟,如果没有则会马上执行scheduleFrameLocked,如果有,则发送一个what为MSG_DO_SCHEDULE_CALLBACK类型的定时消息,等时间到了再处理,其最终处理也是执行scheduleFrameLocked(long now)方法。

这里首先判断USE_VSYNC,如果使用了VSYNC:走scheduleVsyncLocked,即请求VSYNC信号,最终调用doFrame,如果没使用VSYNC,则通过消息执行doFrame。

那么我们先简单了解下请求VSYNC信号的流程:

mDisplayEventReceiver 对应的是FrameDisplayEventReceiver,它继承自 DisplayEventReceiver , 主要是用来接收同步脉冲信号 VSYNC。scheduleVsync()方法通过底层nativeScheduleVsync()向SurfaceFlinger 服务注册,即在下一次脉冲接收后会调用 DisplayEventReceiver的dispatchVsync()方法。这里类似于订阅者模式,但是每次调用nativeScheduleVsync()方法都有且只有一次dispatchVsync()方法回调。

然后再看看接收VSYNC信号:

底层向应用层发送VSYNC信号,java层通过dispatchVsync()接收,最后回调在FrameDisplayEventReceiver的onVsync

可见onVsync()过程是通过FrameHandler向主线程Looper发送了一个自带callback的消息 callback为FrameDisplayEventReceiver。 当主线程Looper执行到该消息时,则调用FrameDisplayEventReceiver.run()方法,紧接着便是调用doFrame。

当Vsync事件到来时,顺序执行4种事件对应CallbackQueue队列中注册的回调。

按时间顺序先后执行CallbackRecord对应的run方法

接开篇讲的

mTraversalRunnable对应:

run方法被执行,所以doTraversal()被执行,开启View的绘制流程。

所以整个绘制过程总的流程如下所示:

简单总结:

参考
https://blog.csdn.net/bluewindtalker/article/details/54017569
https://blog.csdn.net/qian520ao/article/details/80954626
http://gityuan.com/2017/02/25/choreographer/
https://www.jianshu.com/p/47c866f6fb67

第十一周总结

图形用户界面

特征:
图形界面对象及其框架(图形界面对象
之间的包含关系)
图形界面对象的布局(图形界面对象之
间的位置关系)
图形界面对象上的事件响应(图形界面
对象上的动作)
Java图形界面开发的两种技术:AWT
(大量使用Windows的系统函数),
Swing(采用Java实现用户界面,可以
在任意的系统平台上工作)
AWT包工具类
1.组件Component
2.容器Container所有的AWT组件都应
该放到容器中
3.布局管理器Layout Manager

Swing保存在javax.swing包中,所有
的组件都从JComponent扩展出来的

默认对齐方式 左对齐,居中对齐
JLbbel类
更改JLabel的文字样式
使用component类中定义的方法更改使
用的字体。
public void setFont(Font f)
java.awt.Font类

布局管理器

类型:FlowLayout,BorderLayout,

GridLayout,CardLayout,绝对定位。

FlowLayout:流水布局

对齐方式:public static final int ;(常量)
默认对齐为居中对齐且间隔5个像素。
BorderLayout:将版面划分为东南西
北中。public static final String
;(常量)
先在区域中加容器,一般不会加控件让其进
行更复杂的排列

GridLayout:表格形式

使用时需设置显示的行数和列数
留行减列,无论多少按钮首先保证行。

CardLayout:将一组组彼此重叠的组件

进行布局,每次只展现一个界面;
public void * (Container parent)
翻转到*图片
pack:自适应内容

绝对定位:设置绝对坐标

public void setBounds (int x, int y,int
width,int height)

学会应用用在的地方

以上是关于Android图形系统(十一)-Choreographer的主要内容,如果未能解决你的问题,请参考以下文章

第十一周课程总结

一起Talk Android吧(第四百五十一回:View中的事件分发机制)

第十一周课程总结

一起Talk Android吧(第四百一十一回:绘制文字)

一起Talk Android吧(第四百二十一回:绘图中添加阴影)

第十一周课程总结