View的工作原理

参考链接

ViewRootImpl:负责view的布局 测量 绘制

DecorView:
因为oncreate走完,仅仅只是资源的准备工作,实际view的绘制工作是在onresume()中进行的,同时,这里要看ActivityThread的handlerMessage()方法中的RESUME_ACTIVITY,会走handleResumeActivity()方法中,performResumeActivity()方法得到一个ActivityRecord

  ViewManager wm = a.getWindowManager();
  WindowManager.LayoutParams l = r.window.getAttributes();
  a.mDecor = decor;
  l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
  l.softInputMode |= forwardBit;
 if (r.mPreserveWindow) {
     a.mWindowAdded = true;
     r.mPreserveWindow = false;
     ViewRootImpl impl = decor.getViewRootImpl();
       if (impl != null) {
          impl.notifyChildRebuilt();
        }
     }
if (a.mVisibleFromClient) {
    if (!a.mWindowAdded) {
       a.mWindowAdded = true;
       wm.addView(decor, l);//核心代码,l代表的是所有的资源和decorView添加到ViewManager 

wm是一个接口,接口addView,实际就要找到它的一个实现类,也就是WindowManagerGlobal中的addView(),只是这里运用到了一个设计模式,直接分析WindowManagerGlobal的addView即可

核心代码

       //前面一堆系统调用和资源配置就忽略掉了,主要是以下代码
       root = new ViewRootImpl(view.getContext(), display);
       view.setLayoutParams(wparams);
       mViews.add(view);//这三个add实际上是三个list
       mRoots.add(root);
       mParams.add(wparams);
       root.setView(view, wparams, panelParentView);//核心代码

ArrayList<View> mViews = new ArrayList<View>();
ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
ArrayList<WindowManager.LayoutParams> mParams =new ArrayList<WindowManager.LayoutParams>();

ViewRoot的setView()源码分析
内部主要有一个requestLayout() ==> scheduleTraversals()==> mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);==>实际上是调用了这个runable,而这个runable内部实际上是调用了doTraversal()方法

final class TraversalRunnable implements Runnable {
    @Override
    public void run() {
        doTraversal();
    }
}

doTraversal中的核心方法是performTraversals();这里才正式开启了UI的绘制流程

WindowManage.LayoutParams,所有的资源都在这里
Rect frame 绘制了一个矩形。这个矩形并不是画布,而是意思大概就是,先确定他的整体位置

中间是一大堆比较恶心的计算。

下面,有一个测量方法performMeasure(),调用view的measure,再调用自身的onMeasure()方法
performLayout()布局==>view的layout(),再调用自身的onLayout();
performDraw()绘制==>view的draw(),再调用自身的onDraw();
draw中才会有surface画布,这个时候view才会显示出来

setContentView只是资源的准备
onresume才是真正的布局测量绘制

下一篇,对测量 布局 绘制流程的详细分析。

igding wechat
2018 依计行事 持续精进
坚持原创技术分享,您的支持将鼓励我继续创作!