View绘制流程—performResumeActivity—>performTraversals

前言


我们知道AMS启动一个APP(Launcher——>AMS—>MyAPP)会创建ActivityThread。也就是ActivityThread是一个App的真正入口,分析View的绘制流程,我们肯定是以ActivityThread为起点来分析。然后抵达一个方法performTraversals。这个方法是ViewRoot内的一个方法,也是View绘制的真实起点。我们先不讨论它们的具体,本文主要目的是看在它被执行之前都经历了哪些流程。

参考1.Launcher启动流程及初始化
参考2.ActivityThread分析—ActivityThread的main方法是如何被调用的
参考3.ActivityThread分析—ActivityThread的main方法的执行流程分析

代码分析


frameworks\base\core\java\android\app\ActivityThread.java#handleResumeActivity()

wm是WindowManger,其实现类为WindowMangerImpl,我们去看它的addView方法。


    final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
               ......
        if (r != null) {
               ......
            if (r.window == null && !a.mFinished && willBeVisible) {
                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);
                }

               ......
        } else {
               ......
        }
    }

frameworks\base\core\java\android\view\WindowManagerImpl.java#addView()

尾部调用了 ViewRoot root.setView(view, wparams, panelParentView);


    private void addView(View view, ViewGroup.LayoutParams params, boolean nest)
    {
        if (Config.LOGV) Log.v("WindowManager", "addView view=" + view);

        if (!(params instanceof WindowManager.LayoutParams)) {
            throw new IllegalArgumentException(
                    "Params must be WindowManager.LayoutParams");
        }

        final WindowManager.LayoutParams wparams
                = (WindowManager.LayoutParams)params;

        ViewRoot root;
        View panelParentView = null;

        synchronized (this) {
            // Here's an odd/questionable case: if someone tries to add a
            // view multiple times, then we simply bump up a nesting count
            // and they need to remove the view the corresponding number of
            // times to have it actually removed from the window manager.
            // This is useful specifically for the notification manager,
            // which can continually add/remove the same view as a
            // notification gets updated.
            ......
        }
        // do this last because it fires off messages to start doing things
        root.setView(view, wparams, panelParentView);
    }

frameworks\base\core\java\android\view\ViewRoot#setView()



    /**
     * We have one child
     */
    public void setView(View view, WindowManager.LayoutParams attrs,
            View panelParentView) {
        synchronized (this) {
            if (mView == null) {
                ......

                // Schedule the first layout -before- adding to the window
                // manager, to make sure we do the relayout before receiving
                // any other events from the system.
                requestLayout();
                 ......
            }
        }
    }

frameworks\base\core\java\android\view\ViewRoot#requestLayout()


    /**
     * {@inheritDoc}
     */
    public void requestLayout() {
        checkThread();
        mLayoutRequested = true;
        scheduleTraversals();
    }

frameworks\base\core\java\android\view\ViewRoot#scheduleTraversals()

到这里发了一个handler,由于ViewRoot自身继承了handler,所以会发送到它的handlerMessage方法。


    public void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            sendEmptyMessage(DO_TRAVERSAL);
        }
    }

frameworks\base\core\java\android\view\ViewRoot#handleMessage()

可以看到这里就调用了performTraversals();方法,点进去看。


  public void handleMessage(Message msg) {
        ...

     case DO_TRAVERSAL:
                if (mProfile) {
                    Debug.startMethodTracing("ViewRoot");
                }

                performTraversals();//这里

                if (mProfile) {
                    Debug.stopMethodTracing();
                    mProfile = false;
                }
                break;
        ...
  }

frameworks\base\core\java\android\view\ViewRoot#ViewRootImpl()

注意这3个perform的顺序,另外源码版本太低是没有这3个方法的(我的是2.3居然找不出这3个方法,后来去studio内看哎看见),哎可把我一阵好找。

private void performTraversals() { 
    ......
     performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
     ... 
     performLayout(lp, desiredWindowWidth, desiredWindowHeight); 
     ... 
    performDraw()
    ......
 }

猜你喜欢

转载自blog.csdn.net/user11223344abc/article/details/81168087