Android知识进阶

Android View绘制流程总结

2019-01-12  本文已影响224人  CyanStone

最近在学习View流程的绘制,看了几篇不错的博客,自己也跟了下源码,现不打算上篇大论的贴源码了,需要详细的分析过程的,可以参考Android应用层View绘制流程与源码分析,这篇文章写的很详细,现在只做下各个流程的总结,便于不了解的同学迅速了解整个流程,了解整个流程的也可以做迅速的回顾。

绘制起点

Android应用层View绘制流程与源码分析这篇文章里,对绘制起点是这么描述的:

View的绘制,是在我们调用了Activity.setContentView() -> PhoneWindow.setContentView中的mContentParent.addView(mContentParent是FrameLayout)中调用了invalidate()后触发的,invalidate()方法会调用ViewRootImpl.performTraversals(),Activity的整个View树的绘制从这里开始的;

但其实这个描述是不对的,因为我们都知道,View的测量、布局、绘制流程是在ActivityThread调用handleResumeActivity之后,把decorView加入到window,把window add到windowmanager之后才开始的,具体分析,可以看看Activity/Window/View的关系以及View的绘制时机和我再Activity启动后View何时开始绘制(onCreate中还是onResume之后?) 文章里的分析。

//ActivityThread
final void handleResumeActivity(IBinder token,
        boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) { 
     ...
      //执行onResume
      r = performResumeActivity(token, clearHide, reason);
      ....
        if (!a.mWindowAdded) {
                        a.mWindowAdded = true;
                        //触发requestLayout和invalidate方法,开始绘制
                        wm.addView(decor, l);
                    }
}
measure测量
layout布局

getWidth()和getHeight()必须是在layout执行之后才有效,且与getMeasuredWidth()和getMeasuredHeight()不同,所以获取View的实际大小,一定要在layout之后调用getWidth()方法和getHeight()方法!

    void layoutVertical(int left, int top, int right, int bottom) {
        for (int i = 0; i < count; i++) {
                ...
                setChildFrame(child, childLeft, childTop + getLocationOffset(child),
                        childWidth, childHeight);
                childTop += childHeight + lp.bottomMargin + getNextLocationOffset(child);
            }
        }
    }
    
    private void setChildFrame(View child, int left, int top, int width, int height) {
        child.layout(left, top, left + width, top + height);
    }    
draw绘制
invalidate和postInvalidate
requestLayout
  public void requestLayout() {
        ......
        if (mParent != null && !mParent.isLayoutRequested()) {
            mParent.requestLayout();
        }
        ......
    }
@Override
    public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
            checkThread();
            mLayoutRequested = true;
            //View调运requestLayout最终层层上传到ViewRootImpl后最终触发了该方法
            scheduleTraversals();
        }
    }
参考链接

Android应用层View绘制流程与源码分析 (强烈推荐)

Android View 深度分析requestLayout、invalidate与postInvalidate

上一篇下一篇

猜你喜欢

热点阅读