侧边栏壁纸
博主头像
慢行的骑兵博主等级

贪多嚼不烂,欲速则不达

  • 累计撰写 27 篇文章
  • 累计创建 27 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

UI的绘制流程

慢行的骑兵
2021-09-20 / 0 评论 / 0 点赞 / 46 阅读 / 611 字

一.UI的绘制流程大体分析

  • 从ActivityThread中下手
  • sdk版本:28
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
        String reason) {
    //...
    if (r.window == null && !a.mFinished && willBeVisible) {
		//1.参数的初始化 服务于 调用绘制
		//获取到Activity的PhoneWindow
        r.window = r.activity.getWindow();
		//获取到Activity的PhoneWindow的mDecorview
        View decor = r.window.getDecorView();
        decor.setVisibility(View.INVISIBLE);
		//获取到Activity的WindowManager
        ViewManager wm = a.getWindowManager();
		//获取到Activity的Window的LayoutParams
        WindowManager.LayoutParams l = r.window.getAttributes();
		//把mDecorView从Activity记录类中给Activity
        a.mDecor = decor;
        l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
        l.softInputMode |= forwardBit;
        if (r.mPreserveWindow) {
            a.mWindowAdded = true;
            r.mPreserveWindow = false;
            // Normally the ViewRoot sets up callbacks with the Activity
            // in addView->ViewRootImpl#setView. If we are instead reusing
            // the decor view we have to notify the view root that the
            // callbacks may have changed.
            ViewRootImpl impl = decor.getViewRootImpl();
            if (impl != null) {
                impl.notifyChildRebuilt();
            }
        }
        if (a.mVisibleFromClient) {
            if (!a.mWindowAdded) {
                a.mWindowAdded = true;
				//2.调用绘制
                //调用了ViewManager(抽象类,其实现类比较多,这里最终是调用WindowManagerImpl类)的方法
                wm.addView(decor, l);
            } 
			//...
        }

        // If the window has already been added, but during resume
        // we started another activity, then don't yet make the
        // window visible.
    } 
	
	//...
}
  • 分析WindowManagerImpl类的addView方法
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();

public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    applyDefaultToken(params);
    mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}

//WindowManagerImpl类的addView方法
public void addView(View view, ViewGroup.LayoutParams params,
        Display display, Window parentWindow) {
    //...
	
    ViewRootImpl root;
    View panelParentView = null;
	
    synchronized (mLock) {
        //...
	
        root = new ViewRootImpl(view.getContext(), display);
	
        view.setLayoutParams(wparams);
	
        //...
	
        // do this last because it fires off messages to start doing things
        try {
            //分析
            root.setView(view, wparams, panelParentView);
        }
        //...
    }
}
  • ViewRootImpl类的setView
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    synchronized (this) {
        if (mView == null) {
            mView = view;
            //...
			//分析
            requestLayout();
            //...
        }
    }
}
  • requestLayout
public void requestLayout() {
    if (!mHandlingLayoutInLayoutRequest) {
        checkThread();
        mLayoutRequested = true;
        //分析
        scheduleTraversals();
    }
}
  • scheduleTraversals
void scheduleTraversals() {
    if (!mTraversalScheduled) {
        mTraversalScheduled = true;
        mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
        //织物者启动调度线程mTraversalRunnable,分析
        mChoreographer.postCallback(
                Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
        if (!mUnbufferedInputDispatch) {
            scheduleConsumeBatchedInput();
        }
        notifyRendererOfFramePending();
        pokeDrawLockIfNeeded();
    }
}
  • 分析mTraversalRunnable
final class TraversalRunnable implements Runnable {
    @Override
    public void run() {
        //执行调度,分析
        doTraversal();
    }
}
  • doTraversal
void doTraversal() {
    if (mTraversalScheduled) {
        mTraversalScheduled = false;
        mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);

        if (mProfile) {
            Debug.startMethodTracing("ViewAncestor");
        }
		
        //分析
        performTraversals();

        if (mProfile) {
            Debug.stopMethodTracing();
            mProfile = false;
        }
    }
}
  • 分析performTraversals
private void performTraversals() {
        // cache mView since it is used so much below...
        final View host = mView;

        //...

        if (mFirst || windowShouldResize || insetsChanged ||
                viewVisibilityChanged || params != null || mForceNextWindowRelayout) {
            mForceNextWindowRelayout = false;

            //...

            if (!mStopped || mReportNextDraw) {
                boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
                        (relayoutResult&WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE) != 0);
                if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth()
                        || mHeight != host.getMeasuredHeight() || contentInsetsChanged ||
                        updatedConfiguration) {
                    //...

                    if (measureAgain) {
                        //...
                        //分析
                        performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
                    }

                    layoutRequested = true;
                }
            }
        } else {
            //...
        }

        final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw);
        boolean triggerGlobalLayoutListener = didLayout
                || mAttachInfo.mRecomputeGlobalAttributes;
        if (didLayout) {
            //分析
            performLayout(lp, mWidth, mHeight);

            //...
        }

        //...

        if (!cancelDraw && !newSurface) {
            if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
                for (int i = 0; i < mPendingTransitions.size(); ++i) {
                    mPendingTransitions.get(i).startChangingAnimations();
                }
                mPendingTransitions.clear();
            }
            
			//分析
            performDraw();
        }
		
		//...
    }

  • performMeasure、performLayout、performDraw最终就是调用view的测量,摆放和绘制;

二.UI的绘制流程图

01.UI的具体绘制流程

0

评论区