美文网首页
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()

    请求重绘

    相关文章

      网友评论

          本文标题:Choreographer

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