本文转载自微信公众号「Android开发编程」,作者Android开发编程。转载本文请联系Android开发编程公众号。

十余年品牌的成都网站建设公司,超过千家企业网站设计经验.价格合理,可准确把握网页设计诉求.提供定制网站建设、购物商城网站建设、微信小程序、响应式网站开发等服务,我们设计的作品屡获殊荣,是您值得信赖的专业网站设计公司。
Android平台提供两种信号,一种是硬件信号,另一种是软件信号,由SurfaceFlinger进程的一个线程定时发出,硬件信号由硬件发出;
App进程若要通过gpu实现图像绘制,需要在接收到Vsync信号的条件下进行,因此,App进程访问SurfaceFlinger进程获取这个信号,再进行gpu绘制;
Android4.1之后增加了Choreographer机制,用于同Vsync机制配合,统一动画、输入和绘制时机;
Choreographer就是负责获取Vsync同步信号并控制App线程(主线程)完成图像绘制的类;
今天我们就来聊聊Choreographer机制;
- public ViewRootImpl(Context context, Display display) {
 - ...
 - //获取Choreographer实例
 - mChoreographer = Choreographer.getInstance();
 - ...
 - }
 - public static Choreographer getInstance() {
 - return sThreadInstance.get();
 - }
 - private static final ThreadLocal
 sThreadInstance = - new ThreadLocal
 () { - @Override
 - protected Choreographer initialValue() {
 - Looper looper = Looper.myLooper();
 - if (looper == null) {
 - throw new IllegalStateException("The current thread must have a looper!");
 - }
 - return new Choreographer(looper);
 - }
 - };
 
- private Choreographer(Looper looper, int vsyncSource) {
 - mLooper = looper;
 - //使用当前线程looper创建 mHandler
 - mHandler = new FrameHandler(looper);
 - //USE_VSYNC 4.1以上默认是true,表示 具备接受VSync的能力,这个接受能力就是FrameDisplayEventReceiver
 - mDisplayEventReceiver = USE_VSYNC
 - ? new FrameDisplayEventReceiver(looper, vsyncSource)
 - : null;
 - mLastFrameTimeNanos = Long.MIN_VALUE;
 - // 计算一帧的时间,Android手机屏幕是60Hz的刷新频率,就是16ms
 - mFrameIntervalNanos = (long)(1000000000 / getRefreshRate());
 - // 创建一个链表类型CallbackQueue的数组,大小为5,
 - //也就是数组中有五个链表,每个链表存相同类型的任务:输入、动画、遍历绘制等任务(CALLBACK_INPUT、CALLBACK_ANIMATION、CALLBACK_TRAVERSAL)
 - mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];
 - for (int i = 0; i <= CALLBACK_LAST; i++) {
 - mCallbackQueues[i] = new CallbackQueue();
 - }
 - // b/68769804: For low FPS experiments.
 - setFPSDivisor(SystemProperties.getInt(ThreadedRenderer.DEBUG_FPS_DIVISOR, 1));
 - }
 
- //输入事件,首先执行
 - public static final int CALLBACK_INPUT = 0;
 - //动画,第二执行
 - public static final int CALLBACK_ANIMATION = 1;
 - //插入更新的动画,第三执行
 - public static final int CALLBACK_INSETS_ANIMATION = 2;
 - //绘制,第四执行
 - public static final int CALLBACK_TRAVERSAL = 3;
 - //提交,最后执行,
 - public static final int CALLBACK_COMMIT = 4;
 
五种类型任务对应存入对应的CallbackQueue中;
每当收到 VSYNC 信号时,Choreographer 将首先处理 INPUT 类型的任务,然后是 ANIMATION 类型,最后才是 TRAVERSAL 类型。
- private final class FrameHandler extends Handler {
 - public FrameHandler(Looper looper) {
 - super(looper);
 - }
 - @Override
 - public void handleMessage(Message msg) {
 - switch (msg.what) {
 - case MSG_DO_FRAME:
 - doFrame(System.nanoTime(), 0);
 - break;
 - case MSG_DO_SCHEDULE_VSYNC:
 - doScheduleVsync(); // 请求VSYNC信号
 - break;
 - case MSG_DO_SCHEDULE_CALLBACK:
 - doScheduleCallback(msg.arg1);
 - break;
 - }
 - }
 - }
 
- @Override
 - public void requestLayout() {
 - if (!mHandlingLayoutInLayoutRequest) {
 - checkThread();//检查是否在当前线程
 - mLayoutRequested = true;//mLayoutRequested 是否measure和layout布局。
 - scheduleTraversals();
 - }
 - }
 - void scheduleTraversals() {
 - if (!mTraversalScheduled) {//同一帧内不会多次调用遍历
 - mTraversalScheduled = true;
 - mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();//拦截同步Message
 - //Choreographer回调,执行绘制操作
 - mChoreographer.postCallback(
 - Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
 - }
 - }
 
- mChoreographer.postCallback(
 - Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
 - postCallback()->postCallbackDelayed()->postCallbackDelayedInternal():
 
- private void postCallbackDelayedInternal(int callbackType,
 - Object action, Object token, long delayMillis) {
 - synchronized (mLock) {
 - // 当前时间
 - final long now = SystemClock.uptimeMillis();
 - // 回调执行时间,为当前时间加上延迟的时间
 - final long dueTime = now + delayMillis;
 - // obtainCallbackLocked(long dueTime, Object action, Object token)会将传入的3个参数转换为CallbackRecord(具体请看源码,非主要部分,此处略过),然后CallbackQueue根据回调类型将CallbackRecord添加到链表上。
 - mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);
 - if (dueTime <= now) {
 - // 如果delayMillis=0的话,dueTime=now,则会马上执行
 - scheduleFrameLocked(now);
 - } else {
 - // 如果dueTime>now,则发送一个what为MSG_DO_SCHEDULE_CALLBACK类型的定时消息,等时间到了再处理,其最终处理也是执行scheduleFrameLocked(long now)方法
 - Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
 - msg.arg1 = callbackType;
 - msg.setAsynchronous(true);
 - mHandler.sendMessageAtTime(msg, dueTime);
 - }
 - }
 - }
 
- private void scheduleFrameLocked(long now) {
 - if (!mFrameScheduled) {
 - mFrameScheduled = true;
 - if (USE_VSYNC) {
 - // 如果使用了VSYNC,由系统值确定
 - if (DEBUG_FRAMES) {
 - Log.d(TAG, "Scheduling next frame on vsync.");
 - }
 - if (isRunningOnLooperThreadLocked()) {
 - // 请求VSYNC信号,最终会调到Native层,Native处理完成后触发FrameDisplayEventReceiver的onVsync回调,回调中最后也会调用doFrame(long frameTimeNanos, int frame)方法
 - scheduleVsyncLocked();
 - } else {
 - // 在UI线程上直接发送一个what=MSG_DO_SCHEDULE_VSYNC的消息,最终也会调到scheduleVsyncLocked()去请求VSYNC信号
 - Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
 - msg.setAsynchronous(true);
 - mHandler.sendMessageAtFrontOfQueue(msg);
 - }
 - } else {
 - // 没有使用VSYNC
 - final long nextFrameTime = Math.max(
 - mLastFrameTimeNanos / TimeUtils.NANOS_PER_MS + sFrameDelay, now);
 - if (DEBUG_FRAMES) {
 - Log.d(TAG, "Scheduling next frame in " + (nextFrameTime - now) + " ms.");
 - }
 - // 直接发送一个what=MSG_DO_FRAME的消息,消息处理时调用doFrame(long frameTimeNanos, int frame)方法
 - Message msg = mHandler.obtainMessage(MSG_DO_FRAME);
 - msg.setAsynchronous(true);
 - mHandler.sendMessageAtTime(msg, nextFrameTime);
 - }
 - }
 - }
 
- // Enable/disable vsync for animations and drawing.
 - private static final boolean USE_VSYNC = SystemProperties.getBoolean(
 - "debug.choreographer.vsync", true);
 
常量USE_VSYNC,表示是否允许动画和绘制的垂直同步,默认是为true;
判断USE_VSYNC,如果使用了VSYNC:走scheduleVsyncLocked,即请求VSYNC信号,最终调用doFrame;
如果没使用VSYNC,则通过消息执行doFrame;
请求VSYNC信号的流程;
- private void scheduleVsyncLocked() {
 - mDisplayEventReceiver.scheduleVsync();
 - }
 - public void scheduleVsync() {
 - if (mReceiverPtr == 0) {
 - Log.w(TAG, "Attempted to schedule a vertical sync pulse but the display event "
 - + "receiver has already been disposed.");
 - } else {
 - nativeScheduleVsync(mReceiverPtr);
 - }
 - }
 
- private final class FrameDisplayEventReceiver extends DisplayEventReceiver implements Runnable {
 - private boolean mHavePendingVsync;
 - private long mTimestampNanos;
 - private int mFrame;
 - @Override
 - public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
 - //忽略来自第二显示屏的Vsync
 - if (builtInDisplayId != SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
 - scheduleVsync();
 - return;
 - }
 - ...
 - mTimestampNanos = timestampNanos;
 - mFrame = frame;
 - //该消息的callback为当前对象FrameDisplayEventReceiver
 - Message msg = Message.obtain(mHandler, this);
 - msg.setAsynchronous(true);
 - //此处mHandler为FrameHandler
 - mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
 - }
 - @Override
 - public void run() {
 - mHavePendingVsync = false;
 - doFrame(mTimestampNanos, mFrame);
 - }
 - }
 
- void doFrame(long frameTimeNanos, int frame) {
 - final long startNanos;
 - synchronized (mLock) {
 - ...
 - //是否有跳帧,如果有那么就打印log并且修正偏差
 - }
 - //执行callback
 - try {
 - Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Choreographer#doFrame");
 - AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS);
 - mFrameInfo.markInputHandlingStart();
 - doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
 - mFrameInfo.markAnimationsStart();
 - doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
 - mFrameInfo.markPerformTraversalsStart();
 - doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
 - doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
 - } finally {
 - AnimationUtils.unlockAnimationClock();
 - Trace.traceEnd(Trace.TRACE_TAG_VIEW);
 - }
 - if (DEBUG_FRAMES) {
 - final long endNanos = System.nanoTime();
 - Log.d(TAG, "Frame " + frame + ": Finished, took "
 - + (endNanos - startNanos) * 0.000001f + " ms, latency "
 - + (startNanos - frameTimeNanos) * 0.000001f + " ms.");
 - }
 - }
 
doFrame方法做的就是渲染下一帧,检测是否卡顿并修补卡顿,然后开始做渲染工作,doCallbacks方法的参数:
- void doCallbacks(int callbackType, long frameTimeNanos) {
 - CallbackRecord callbacks;
 - synchronized (mLock) {
 - final long now = SystemClock.uptimeMillis();
 - //从指定类型的CallbackQueue队列中查找执行时间到的CallbackRecord
 - callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked(now);
 - if (callbacks == null) {
 - return;
 - }
 - mCallbacksRunning = true;
 - }
 - try {
 - //由于CallbackQueues是按时间先后顺序排序的,因此遍历执行所有时间到的CallbackRecord
 - for (CallbackRecord c = callbacks; c != null; c = c.next) {
 - c.run(frameTimeNanos);
 - }
 - } finally {
 - synchronized (mLock) {
 - mCallbacksRunning = false;
 - do {
 - final CallbackRecord next = callbacks.next;
 - recycleCallbackLocked(callbacks);
 - callbacks = next;
 - } while (callbacks != null);
 - }
 - }
 - }
 
Choreographer内部维护了这四种链表,渲染每一帧的时候都会从上往下的去执行相应的渲染操作,有输入那么就先渲染输入队列,有动画就渲染动画,然后遍历,然后提交;
                文章标题:屏幕刷新机制Choreographer原理分析
                
                网站地址:http://www.csdahua.cn/qtweb/news26/289926.html
            
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网