android view的绘制流程

源码基于8.0

oncreate()获取view的宽高为0

activity启动流程(https://www.jianshu.com/p/4a20d9d68482
),最后一步,ams通过binder机制向app进程发送attachapplication请求,然后app收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY,然后执行handleLaunchActivity()。
1.performLaunchActivity(调用oncreate onstart)
2.handleResumeActivity(调用onresume-->window.addview())
经过一系列调用,最后走到ViewRootImpl的performTraversals()方法(之后流程见图view的绘制流程.png),开始view的measure,layout,draw流程。(来到这顺便也可以通过源码发现requestLayout,invalidate的区别)所以,在oncreate方法中,view是还没有测量的,获取的宽高为0。下面代码段注释1-2处。

final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,
            boolean reallyResume) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();
        //===注释1:调用activity的声名周期onresume()====
        ActivityClientRecord r = performResumeActivity(token, clearHide);

        if (r != null) {
            final Activity a = r.activity;

            if (localLOGV) Slog.v(
                TAG, "Resume " + r + " started activity: " +
                a.mStartedActivity + ", hideForNow: " + r.hideForNow
                + ", finished: " + a.mFinished);

            final int forwardBit = isForward ?
                    WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;

            // If the window hasn't yet been added to the window manager,
            // and this guy didn't finish itself or start another activity,
            // then go ahead and add the window.
            boolean willBeVisible = !a.mStartedActivity;
            if (!willBeVisible) {
                try {
                    willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
                            a.getActivityToken());
                } catch (RemoteException e) {
                }
            }
            if (r.window == null && !a.mFinished && willBeVisible) {
                //===注释2:获取activity的window,decoerview为window的内部类,          
                //也是view的根部局。通过wm.addview方法,将ViewRootImpl对象, 
               //然后调用其setView()方法。其中setView()方法经过一些列折腾,最终 
               //调用了performTraversals()方法。开始view的测量布局绘制流程。
                r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                ViewManager wm = a.getWindowManager();
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;
                if (a.mVisibleFromClient) {
                    a.mWindowAdded = true;
                    wm.addView(decor, l);
                }
               //以下代码略
    }

view的绘制流程.png

measure流程

measure,测量。确定view的大小。
调用measure()方法,进行一些逻辑处理,然后调用onMeasure()方法,在其中调用setMeasuredDimension()设定View的宽高信息,完成View的测量操作。
(注 MeasureSpec如何确定,这里不就提了,需要注意的是,当自定义view时,需重写measure(),以区别wrap_content和match_parent)


measure.png

layout流程

layout流程中,viewgroup需要根据布局的特性来重写onlayout方法。


layout.png

draw流程

public void draw(Canvas canvas) {
       ...
    int saveCount;
    if (!dirtyOpaque) {
          // 步骤1: 绘制本身View背景
        drawBackground(canvas);
    }

        // 如果有必要,就保存图层(还有一个复原图层)
        // 优化技巧:
        // 当不需要绘制 Layer 时,“保存图层“和“复原图层“这两步会跳过
        // 因此在绘制的时候,节省 layer 可以提高绘制效率
        final int viewFlags = mViewFlags;
        if (!verticalEdges && !horizontalEdges) {

        if (!dirtyOpaque) 
             // 步骤2:绘制本身View内容  默认为空实现,  自定义View时需要进行复写
            onDraw(canvas);
    
        ......
        // 步骤3:绘制子View   默认为空实现 单一View中不需要实现,ViewGroup中已经实现该方法
        dispatchDraw(canvas);
  
        ........

        // 步骤4:绘制滑动条和前景色等等
        onDrawScrollBars(canvas);

       ..........
        return;
    }
    ...    
    }

view和viewgroup都必须重写ondraw方法来完成view的绘制流程。

总结

实现自定义view的话,根据具体需要实现的效果,正确重写onMeasure,onlayout,ondraw方法即可。
最后,附上开发过程中偶尔上传过github的demo https://github.com/liujiyi/UIDemo

参考:android开发艺术探索第四章
博客:https://www.jianshu.com/p/3d2c49315d68

你可能感兴趣的:(android view的绘制流程)