Android界面显示_视图Choreographer控制

  • GPU/CPU生产帧率和屏幕消费帧率的生产者消费者模式

  • 掉帧,双缓存,三缓存

  • SurfaceFlinger进程发出vsync信号

  • Choreographer(ThreadLocal持有,即ui线程持有)负责获取Vsync同步信号并控制App线程(主线程)完成图像绘制的类

  • 主线程中初始化变量时,创建Choreographer对象,绑定主线程Looper

  • Choreographer通过DisplayEventReceiver通过JNI调用,利用Binder机制接收surfaceflinger进程底层Vsync信号,请求帧画面显示控制。在需要绘制时,发起请求。底层初始化(nativeInit),发起请求(scheduleVsync),实现回调(dispatchVsync)

  • DisplayEventReceiver收到底层各种类型的信号,在doFrame()方法中处理doCallbacks(int callbackType, long frameTimeNanos)

    void doFrame(long frameTimeNanos, int frame) {         ...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);            doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameTimeNanos);            mFrameInfo.markPerformTraversalsStart();            doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);            doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);        } finally {                   AnimationUtils.unlockAnimationClock();            Trace.traceEnd(Trace.TRACE_TAG_VIEW);        }  ...}
  • callbackType类型:

    • Choreographer.CALLBACK_INPUT(控制同步处理输入Input)
    • Choreographer.CALLBACK_ANIMATION(控制同步动画Animation)
    • Choreographer.CALLBACK_TRAVERSAL(触发ViewRootImpl的doTraversal方法,实现一次遍历绘制)
    • Choreographer.CALLBACK_INSETS_ANIMATION
    • Choreographer.CALLBACK_COMMIT(遍历完成的提交操作,用来修正动画启动时间)
  • 自定义doFrame监听每一帧渲染时间,获取设备当前帧率(开源项目:Tiny Dancer)

    Choreographer.getInstance().postFrameCallback(new FPSFrameCallback());public class FPSFrameCallback implements Choreographer.FrameCallback{       @Override  public void doFrame(long frameTimeNanos){             //do something  }
  • doCallbacks代码如下:

    void doCallbacks(int callbackType, long frameTimeNanos) {               CallbackRecord callbacks;        synchronized (mLock) {                   // We use "now" to determine when callbacks become due because it's possible            // for earlier processing phases in a frame to post callbacks that should run            // in a following phase, such as an input event that causes an animation to start.            final long now = System.nanoTime();            callbacks = mCallbackQueues[callbackType].extractDueCallbacksLocked(                    now / TimeUtils.NANOS_PER_MS);            if (callbacks == null) {                       return;            }            mCallbacksRunning = true;            // Update the frame time if necessary when committing the frame.            // We only update the frame time if we are more than 2 frames late reaching            // the commit phase.  This ensures that the frame time which is observed by the            // callbacks will always increase from one frame to the next and never repeat.            // We never want the next frame's starting frame time to end up being less than            // or equal to the previous frame's commit frame time.  Keep in mind that the            // next frame has most likely already been scheduled by now so we play it            // safe by ensuring the commit time is always at least one frame behind.            if (callbackType == Choreographer.CALLBACK_COMMIT) {                       final long jitterNanos = now - frameTimeNanos;                Trace.traceCounter(Trace.TRACE_TAG_VIEW, "jitterNanos", (int) jitterNanos);                if (jitterNanos >= 2 * mFrameIntervalNanos) {                           final long lastFrameOffset = jitterNanos % mFrameIntervalNanos                            + mFrameIntervalNanos;                    if (DEBUG_JANK) {                               Log.d(TAG, "Commit callback delayed by " + (jitterNanos * 0.000001f)                                + " ms which is more than twice the frame interval of "                                + (mFrameIntervalNanos * 0.000001f) + " ms!  "                                + "Setting frame time to " + (lastFrameOffset * 0.000001f)                                + " ms in the past.");                        mDebugPrintNextFrameTimeDelta = true;                    }                    frameTimeNanos = now - lastFrameOffset;                    mLastFrameTimeNanos = frameTimeNanos;                }            }        }        try {                   Trace.traceBegin(Trace.TRACE_TAG_VIEW, CALLBACK_TRACE_TITLES[callbackType]);            for (CallbackRecord c = callbacks; c != null; c = c.next) {                       if (DEBUG_FRAMES) {                           Log.d(TAG, "RunCallback: type=" + callbackType                            + ", action=" + c.action + ", token=" + c.token                            + ", latencyMillis=" + (SystemClock.uptimeMillis() - c.dueTime));                }                c.run(frameTimeNanos);            }        } finally {                   synchronized (mLock) {                       mCallbacksRunning = false;                do {                           final CallbackRecord next = callbacks.next;                    recycleCallbackLocked(callbacks);                    callbacks = next;                } while (callbacks != null);            }            Trace.traceEnd(Trace.TRACE_TAG_VIEW);        }    }

    从mCallbackQueues中取出CallbackRecord,for循环遍历执行c.run(frameTimeNanos);

  • CallbackRecord代码如下:

        private static final class CallbackRecord {               public CallbackRecord next;        public long dueTime;        public Object action; // Runnable or FrameCallback        public Object token;        @UnsupportedAppUsage        public void run(long frameTimeNanos) {                   if (token == FRAME_CALLBACK_TOKEN) {                       ((FrameCallback)action).doFrame(frameTimeNanos);            } else {                       ((Runnable)action).run();            }        }    }

    CallbackRecord的run方法中((Runnable)action).run();

  • CallbackRecord对象中的(Runnable)action是我们在ViewRootImpl类当中的InvalidateOnAnimationRunnable、mConsumedBatchedInputRunnable、mTraversalRunnable添加到Choreographer中来的。那么回到View的流程中,比如收到Vsync信号后,就会回调mTraversalRunnable的run()方法,再次发起一次measure、layout、draw流程,那么也就和Vsync信号对接上了

更多相关文章

  1. android中UI主线程与子线程深入分析
  2. Android的Looper类使用的5个要点
  3. android多线程handler+runOnUithread+view.post+handler.post
  4. Android网络编程 HttpUrlConnection HttpClient AsyncTask
  5. android根据图片的uri获取图片的物理路径
  6. Android遍历所有文件夹和子目录搜索文件
  7. Android(安卓)线程中更新UI
  8. Linux中遍历目录
  9. Android访问网络(可以正常使用)

随机推荐

  1. Android签名漏洞分析
  2. Android(安卓)应用程序之间数据共享 - Co
  3. Android平台上的11个感应器你都知道吗
  4. Android热补丁技术—dexposed原理简析(手
  5. 一些关于 Activity 的技巧
  6. GalHttprequest类库简介——android平台
  7. One省电卫士 - Android内核级省电App
  8. 风投称Android将像Windows一样主宰移动市
  9. Smack和Asmack
  10. Android(安卓)网络访问框架 NiceDay 发布