美文网首页
Choreographer

Choreographer

作者: 杨殿生 | 来源:发表于2020-04-30 11:59 被阅读0次

他是控制应用进程绘制时机的,会在收到Vsync信号后调用应用进程的刷新

Choreographer创建,他是跟ViewRootImpl一起创建的(在ViewRootImpl的构造函数中)

   public static Choreographer getInstance() {
        return sThreadInstance.get();
    }

他是通过ThreadLocal存储的也就是说一个线程只有一个Choreographer

DecorView在添加到ViewManager时会调用requestLayout

public void requestLayout() {
   scheduleTraversals();
}
void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
        }
    }

1、设置一个标记防止多次调用requestLayout
2、设置消息屏障(屏蔽普通消息,放行异步消息)
3、向Choreographer添加消息

  private void postCallbackDelayedInternal(int callbackType,
            Object action, Object token, long delayMillis) {
           ····
            mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);
           ····
            scheduleFrameLocked(now);
    }
private void scheduleFrameLocked(long now) {
        if (!mFrameScheduled) {
                // If running on the Looper thread, then schedule the vsync immediately,
                // otherwise post a message to schedule the vsync from the UI thread
                // as soon as possible.
                if (isRunningOnLooperThreadLocked()) {
                    scheduleVsyncLocked();
                } else {
                    Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
                    msg.setAsynchronous(true);
                    mHandler.sendMessageAtFrontOfQueue(msg);
                }
            }
        }
    }

如果当前线程是Choreographer工作线程,通过 scheduleVsyncLocked();向SurfaceFlinger发送Vsync请求(通过socketpair)requestNextVsync,在构造函数中通过parcel获取。BitTube,这个Socket是surfaceflinger创建后传递过来的。否则发送消息到工作线程中

private final class FrameDisplayEventReceiver extends DisplayEventReceiver
            implements Runnable {
    
        @Override
        public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
            ···
            mTimestampNanos = timestampNanos;
            mFrame = frame;
            Message msg = Message.obtain(mHandler, this);
            msg.setAsynchronous(true);
            mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
        }

        @Override
        public void run() {
            doFrame(mTimestampNanos, mFrame);
        }
    }

信号发送回来会在这里接收到

void doFrame(long frameTimeNanos, int frame) {
       
            long intendedFrameTimeNanos = frameTimeNanos;
            startNanos = System.nanoTime();
            final long jitterNanos = startNanos - frameTimeNanos;
            if (jitterNanos >= mFrameIntervalNanos) {
                final long skippedFrames = jitterNanos / mFrameIntervalNanos;
                //跳过帧数过多
                if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) {
                    Log.i(TAG, "Skipped " + skippedFrames + " frames!  "
                            + "The application may be doing too much work on its main thread.");
                }
                final long lastFrameOffset = jitterNanos % mFrameIntervalNanos;
                frameTimeNanos = startNanos - lastFrameOffset;
            }

            if (frameTimeNanos < mLastFrameTimeNanos) {
                scheduleVsyncLocked();
                return;
            }

            mFrameInfo.setVsync(intendedFrameTimeNanos, frameTimeNanos);
            mFrameScheduled = false;
            mLastFrameTimeNanos = frameTimeNanos;

            ····
            doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
            doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
            doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
            doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);

    }

执行callback

  void doTraversal() {
        if (mTraversalScheduled) {
            mTraversalScheduled = false;
            mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
            performTraversals();
        }
    }

在接到Vsync信号后,执行doTraversal
1、撤销标记位
2、撤销消息屏障
3、执行performTraversals()

请求重绘

相关文章

  • Android 屏幕刷新机制 Choreographer 原理分

    前言[#%E5%89%8D%E8%A8%80] Choreographer 类介绍[#choreographer-...

  • Choreographer

    ChoreographerLogcat使用关键词Choreographer进行过滤,对App做一些操作,一般能看到...

  • Choreographer

    他是控制应用进程绘制时机的,会在收到Vsync信号后调用应用进程的刷新 Choreographer创建,他是跟Vi...

  • 深挖view绘制流程(二)

    Choreographer Choreographer的中文翻译是编舞者、舞蹈编导的意思,为什么起这个名字呢?因为...

  • Android刷新机制

    ViewRootImpl Choreographer doScheduleVsync Looper.pollInner

  • 安卓显示

    Android 之 VSYNC、 ChoreographerAndroid 渲染机制, Choreographer...

  • Vsync流程

    从ViewRootImpl 到Choreographer再到ViewRootImplVsync.png

  • Choreographer 解析

    一、概述 在 Logcat 中使用关键词 Choreographer 进行过滤,对 App 做一些操作,一般能看到...

  • Choreographer源码

    CallbackQueue负责存储 三种类型的事件,public CallbackRecord extractDu...

  • 关于Choreographer

    Choreographer应用最广泛的是其postCallback()方法可以提供在vsync信号来到时进行回调,...

网友评论

      本文标题:Choreographer

      本文链接:https://www.haomeiwen.com/subject/psczwhtx.html