源码跟踪之刷新流程:从invalidate到onDraw

Instrumentation源码阅读方法可参考:Android源码阅读技巧

SDK版本名称: Pie
API Level: 28

一、源码调用时序图

View#invalidate时序图.jpg

二、流程总结

View刷新是使用的注册监听机制接收底层刷新信号被动刷新的。
相关方法在Choreographer.java(编舞)内部类FrameDisplayEventReceiver中:

  • 注册监听:void scheduleVsyncLocked()
  • 接收信号:void onVsync(long timestampNanos, int builtInDisplayId, int frame)

而在ViewRootImpl.java中对应方法为:

  • 注册监听:void scheduleTraversals()
  • 接收信号:void performTraversals()

只有当app 主动注册一个信号监听后,才能接收到下一个屏幕刷新信号。只有当View 发起了刷新请求时,app 才会去注册监听下一个屏幕刷新信号。在view层的相关方法如下:

  • 主动刷新:invalidate()包括postInvalidate、postInvalidateDelayed
  • 接收到信号后根据情况会调用onMeasureonLayoutonDraw

三、相关文章:

  • Android 屏幕刷新机制

四、流程记录

  • 代码跟踪记录,只保留了关键代码,其余代码用...替代。
  • java类名可点击,将跳转到Android社区的sdk源代码文件。
  • 跟踪记录的意义在于,在需要研究流程中某个环节细节问题时,可以快速定位。

1. android.view.View.java

    public void invalidate(...) {
        invalidateInternal(...);
    }
    void invalidateInternal(...) {
        ...
        p.invalidateChild(...);
        ...
    }
    public final void measure(...) {
        ...
        onMeasure(...);
        ...
    }
    public void layout(...) {
        if (....) {
            onMeasure(...);
            ...
        }
        ...
        onLayout(...)
        ...
    }
    public void draw(...) {
        ...
        if (...) onDraw(..);
        ...
    }

2. android.view.ViewGroup.java

    public final void invalidateChild(...) {
        ...
        onDescendantInvalidated(...);
        ...
    }
    public void onDescendantInvalidated(...) {
        ...
        mParent.onDescendantInvalidated(...);
        ...
    }

3. android.view.ViewRootImpl.java

    public void onDescendantInvalidated(...) {
        ...
        invalidate();
    }
    void invalidate() {
        ...
        scheduleTraversals();
        ...
    }
    final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
    void scheduleTraversals() {
        ...
        mChoreographer.postCallback(...,mTraversalRunnable,...);
        ...
    }
    final class TraversalRunnable implements Runnable {
        public void run() {
            doTraversal();
        }
    }
    void doTraversal() {
        ...
        performTraversals();
        ...
    }
    private void performTraversals() {
        ...
        performMeasure(...);
        ...
        performLayout(...)
        ...
        performDraw();
        ...
    }
    private void performMeasure(...) {
        ...
        mView.measure(...);
        ...
    }
    private void performLayout(...) {
        ...
        final View host = mView;
        ...
        host.layout(...);
        ...
    }
    private void performDraw() {
        ...
        boolean canUseAsync = draw(...);
        ...
    }
    private boolean draw(...) {
        ...
        if (!drawSoftware(...)) {
            ...
        }
        ...
    }
    private boolean drawSoftware(...) {
        ...
        mView.draw(canvas);
        ...
    }

4. android.view.Choreographer.java

    private final FrameHandler mHandler;
    private final CallbackQueue[] mCallbackQueues;
    private Choreographer(...) {
        ...
        mHandler = new FrameHandler(...);
        ...
        mCallbackQueues = new CallbackQueue[.];
        ...
    }
    public void postCallback(..., Runnable action,...) {
        postCallbackDelayed(..., action,...);
    }
    public void postCallbackDelayed(..., Runnable action,...) {
        ...
        postCallbackDelayedInternal(..., action,...);
    }
    private void postCallbackDelayedInternal(...,Object action,...) {
        ...
        mCallbackQueues[.].addCallbackLocked(..., action,...);
        ...
        if (...) {
            scheduleFrameLocked(...);
        } else {
            mHandler.sendMessage...
        }
        ...
    }
    private final class FrameHandler extends Handler {
        ...
        public void handleMessage(...) {
            ...
            doFrame(...);
            ...
            doScheduleVsync();
            ...
            doScheduleCallback(...);
            ...
        }
    }
    void doFrame(...) {
        ...
        scheduleVsyncLocked();
        return;
        ...
        doCallbacks(...)
        ...
    }
    void doCallbacks(...) {
        ...
        callbacks = mCallbackQueues[.].extractDueCallbacksLocked(..)
        ...
        for (CallbackRecord c = callbacks; c != null; c = c.next) {
           ...
           c.run(...);
        }
        ...
    }
    void doScheduleVsync() {
        ...
        scheduleVsyncLocked();
        ...
    }
    void doScheduleCallback(...) {
        ...
        scheduleFrameLocked(...);
        ...
    }
    private void scheduleFrameLocked(...) {
        ...
        if(...){
            ...
            if(...){
                scheduleVsyncLocked();
            }else{
                mHandler.sendMessage...
            }
        }else{
            ...
            mHandler.sendMessage...
        }
    }
    private void scheduleVsyncLocked() {
        mDisplayEventReceiver.scheduleVsync();
    }
    private final class FrameDisplayEventReceiver extends DisplayEventReceiver implements Runnable {
        ...
        public void onVsync(...) {
            ...
            nativeScheduleVsync(...);
            return;
            ...
            mHandler.sendMessage...
        }
        ...
        public void run() {
            ...
            doFrame(...);
        }
    }
    private static final class CallbackRecord {
        ...
        public void run(...) {
            ...
            ((Runnable)action).run();
            ...
        }
    }

5. android.view.DisplayEventReceiver.java

    @FastNative
    private static native void nativeScheduleVsync(long receiverPtr);
    
    public void scheduleVsync() {
        ...
        nativeScheduleVsync(mReceiverPtr);
        ...
    }

你可能感兴趣的:(源码跟踪之刷新流程:从invalidate到onDraw)