源码分析:Activity加载并显示View的流程分析(二)

上一篇,源码分析:Activity加载并显示View的流程分析(一),分析了Activity的setContentView()方法是怎么一步步把xml的layoutId资源文件解析并放到DecorView里面的。
这一篇,我们就分析下,这个DecorView的测量,绘制并显示出来的过程。

之前分析Activity生命周期调用的时候(Activity的生命周期调用(二)),我们知道,会调用ActivityThread的handleResumeActivity()方法。
Activity的View渲染,测量到加载到显示在页面上,其实也是在这个方法里面执行的。
下面,我们就从这个方法开始分析,它是怎么把View渲染并显示到页面上的。

先看张随便画的图
View的渲染过程

开始分析

ActivityThread.handleResumeActivity()方法

final void handleResumeActivity(IBinder token,
            boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
        ActivityClientRecord r = mActivities.get(token);
       	//之前分析过,这里会执行Activity的onResume()方法
        r = performResumeActivity(token, clearHide, reason);

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

            

            boolean willBeVisible = !a.mStartedActivity;
            if (!willBeVisible) {
                try {
                    willBeVisible = ActivityManager.getService().willActivityBeVisible(
                            a.getActivityToken());
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
            if (r.window == null && !a.mFinished && willBeVisible) {
				//获取到Activity的Window(PhoneWindow)
                r.window = r.activity.getWindow();
				//获取Window的DecorView
                View decor = r.window.getDecorView();
				//把DecorView置为不显示
                decor.setVisibility(View.INVISIBLE);
				//这里获取的是PhoneWindow里面的WindowManagerImpl类
                ViewManager wm = a.getWindowManager();
				//获取LayoutParams
                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) {
					//如果Activity的mWindowAdded标志是false
                    if (!a.mWindowAdded) {
						//把mWindowAdded标志改为true
                        a.mWindowAdded = true;
						//并把DecorView和LayoutParams添加到WindowManager里面
						//WindowManagerImpl的addView()方法
                        wm.addView(decor, l);
                    } else {
                        
						//如果已经添加了,调用Activity的onWindowAttributesChanged()方法
                        a.onWindowAttributesChanged(l);
                    }
                }

	            ...

            // The window is now visible if it has been added, we are not
            // simply finishing, and we are not starting another activity.
            if (!r.activity.mFinished && willBeVisible
                    && r.activity.mDecor != null && !r.hideForNow) {
                r.activity.mVisibleFromServer = true;
                mNumVisibleActivities++;
                if (r.activity.mVisibleFromClient) {
					//调用Activity的makeVisible()方法
                    r.activity.makeVisible();
                }
            }


            // Tell the activity manager we have resumed.
            if (reallyResume) {
                try {
                    ActivityManager.getService().activityResumed(token);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            }

        } else {
            // If an exception was thrown when trying to resume, then
            // just end this activity.
            try {
                ActivityManager.getService()
                    .finishActivity(token, Activity.RESULT_CANCELED, null,
                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
    }

这个方法都做的事情:

  • 1,获取Activity的window(其实是PhoneWindow)(r.activity.getWindow())

    获取Activity的window。window在activity的attach()方法里初始化,其实就是PhoneWindow

  • 2,获取window里面的DecorView(r.window.getDecorView())

    在第一部分分析的时候,我们知道把DecorView放到了Window里。

  • 3,把DecorView置为View.INVISIBLE 不显示

  • 4,获取WindowManager(WindowManagerImpl)(ViewManager wm = a.getWindowManager())

    在Activity里面获取的WindowManager,内部会通过Window来获取。

  • 5,把DecorView添加到WindowManager里面(wm.addView(decor, l))

    下面分析

  • 6,调用Activity的makeVisible()

    把DecorView设置为可见

下面我们就生面的调用过程。来一个一个分析


1,获取Activity的window(其实是PhoneWindow)

activity.getWindow();

    public Window getWindow() {
        return mWindow;
    }

我们看到直接返回的是成员变量mWindow。
我们再看看attach里面mWindow的初始化。

	final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window, ActivityConfigCallback activityConfigCallback) {
        attachBaseContext(context);
		
		...

		//初始化Window
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
            mWindow.setSoftInputMode(info.softInputMode);
        }
        if (info.uiOptions != 0) {
            mWindow.setUiOptions(info.uiOptions);
        }
		//获取WindowManager,其实是调用了PhoneWindow.getWindowManager()方法
        mWindowManager = mWindow.getWindowManager();

		...

    }

可以看到getWindow()获取的就是PhoneWindow。

下面就是从Window获取DecorView。
看下r.window.getDecorView()


2,获取window里面的DecorView(r.window.getDecorView())

上面我们知道了Window就是PhoneWindow,我们直接看下PhoneWindow.getDecorView()方法。

public class PhoneWindow extends Window{
	...

    @Override
    public final View getDecorView() {
        if (mDecor == null || mForceDecorInstall) {
			//如果DecorView是null的话,调用installDecor()方法
            installDecor();
        }
        return mDecor;
    }

	...

}

这个方法就是获取DecorView,如果是Null的话,调用installDecor()方法,来初始化。
在上个部分,我们已经看过这个方法了。这里就不分析了。


3,把DecorView置为View.INVISIBLE 不显示

这个DecorView就是上面从Window里面获取的View,并设置View不显示。


4,获取WindowManager(WindowManagerImpl)(ViewManager wm = a.getWindowManager())

从Activity里面获取WindowManager,先看下Activity.getWindowManager()方法

    public WindowManager getWindowManager() {
        return mWindowManager;
    }

mWindowManager也是成员变量,在attach()方法初始化的。我们再看下这个方法

	final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window, ActivityConfigCallback activityConfigCallback) {
        attachBaseContext(context);
		
		...

		//初始化Window
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
            mWindow.setSoftInputMode(info.softInputMode);
        }
        if (info.uiOptions != 0) {
            mWindow.setUiOptions(info.uiOptions);
        }
		//获取WindowManager,调用了Window.getWindowManager()方法
        mWindowManager = mWindow.getWindowManager();

		...

    }

下面,看下Window.getWindowManager()方法。获取的WindowManager

    public WindowManager getWindowManager() {
        return mWindowManager;
    }

直接是成员变量,我们看下赋值

public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
            boolean hardwareAccelerated) {
        mAppToken = appToken;
        mAppName = appName;
        mHardwareAccelerated = hardwareAccelerated
                || SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
        if (wm == null) {
            wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
        }
		//这里给WindowManager赋值了
        mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
    }

看到是调用了createLocalWindowManager()方法给WindowManager赋值的。看下

    public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
        return new WindowManagerImpl(mContext, parentWindow);
    }

可以看到,这里是直接new了一个WindowManagerImpl出来。所以WindowManager实际上就是WindowManagerImpl。


5,把DecorView添加到WindowManager里面(wm.addView(decor, l))

再这里把DecorView添加到了WindowManager里面,这里我们知道WindowManager实际上就是WindowManagerImpl。
直接看下WindowManagerImpl.addView(decor, l)

public final class WindowManagerImpl implements WindowManager {

	 @Override
    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
		//内部是通过WindowManagerGlobal类来完成的
        mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
    }

}

添加View,内部是通过WindowManagerGlobal来完成的,看下WindowManagerGlobal.addView()方法

public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
        
		...
		
        ViewRootImpl root;
        View panelParentView = null;

        synchronized (mLock) {
            
			...

         	//创建ViewRootImpl
            root = new ViewRootImpl(view.getContext(), display);
			//给DecorView设置LayoutParam
            view.setLayoutParams(wparams);
			//把DecorView放到集合
            mViews.add(view);
			//把ViewRootImpl放到集合
            mRoots.add(root);
			//把LayoutParam设置集合
            mParams.add(wparams);

            try {
				//调用ViewRootImpl的setView()方法
                root.setView(view, wparams, panelParentView);
            } catch (RuntimeException e) {
                // BadTokenException or InvalidDisplayException, clean up.
                if (index >= 0) {
                    removeViewLocked(index, true);
                }
                throw e;
            }
        }
    }

这个addView()方法,主要做了:

  • 1,创建ViewRootImpl
  • 2,给DecorView设置LayoutParam
  • 3,把DecorView,ViewRootImpl,LayoutParam分别保存起来
  • 4,调用ViewRootImpl.setView()方法

下面看下ViewRootImpl.setView()方法

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
        synchronized (this) {
            if (mView == null) {
                mView = view;

                ...

                // 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.
				//翻译:在添加到WindowManager之前,先布局一次。来确保系统接收到其他事件时候,可以再次布局
                requestLayout();

				...

                try {
                    mOrigWindowType = mWindowAttributes.type;
                    mAttachInfo.mRecomputeGlobalAttributes = true;
                    collectViewAttributes();
                    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(),
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mOutsets, mInputChannel);
                } catch (RemoteException e) {
                    mAdded = false;
                    mView = null;
                    mAttachInfo.mRootView = null;
                    mInputChannel = null;
                    mFallbackEventHandler.setView(null);
                    unscheduleTraversals();
                    setAccessibilityFocus(null, null);
                    throw new RuntimeException("Adding window failed", e);
                } finally {
                    if (restore) {
                        attrs.restore();
                    }
                }

               ...
				//View的mParent属性设置为ViewRootImpl
				view.assignParent(this);

            }
        }
    }

ViewRootImpl.setView()方法,主要做了2个事情:

  • 1, requestLayout();

    执行view的onMeasure(),onLayout,onDraw()绘制流程		
    
  • 2, mWindowSession.addToDisplay()方法

    把View显示出来,这个里面涉及到了Window Session ,WindowManagerService等,暂时不分析。
    

先看下第一个

requestLayout()方法

    @Override
    public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
            checkThread();
            mLayoutRequested = true;
            scheduleTraversals();
        }
    }

先检查了线程,然后,调用了scheduleTraversals()方法。
看下scheduleTraversals()方法。

void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
			//VSync 信号,每16毫秒产生一个。
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            if (!mUnbufferedInputDispatch) {
                scheduleConsumeBatchedInput();
            }
            notifyRendererOfFramePending();
            pokeDrawLockIfNeeded();
        }
    }

这里出现了VSync 信号,每16毫秒会产生一个。这里,我们看下mTraversalRunnable线程。

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

这里执行了doTraversal()方法,看下

void doTraversal() {
        if (mTraversalScheduled) {
            mTraversalScheduled = false;
            mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
			//执行了performTraversals()方法
            performTraversals();

        }
    }

我们看下 performTraversals()
这个方法有800多行,我们只找其中关键的几行代码

 private void performTraversals() {
        ...

		// 执行performMeasure()方法
        performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
		boolean measureAgain = false;
		
		//这里可以看出来,如果有weight权重的话,会多执行一次performMeasure()方法
		if (lp.horizontalWeight > 0.0f) {
              width += (int) ((mWidth - width) * lp.horizontalWeight);
              childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(width,
                                MeasureSpec.EXACTLY);
              measureAgain = true;
         }
        if (lp.verticalWeight > 0.0f) {
             height += (int) ((mHeight - height) * lp.verticalWeight);
             childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height,
                                MeasureSpec.EXACTLY);
             measureAgain = true;
         }

         if (measureAgain) {

             performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
         }        
            
		...
		
		//执行performLayout()方法
		performLayout(lp, mWidth, mHeight);		

		...

		//执行performDraw()方法
		performDraw();    
 }

这里看到performTraversals()方法主要做的是三件事情:
1,执行performMeasure()方法
2,执行performLayout()方法
3,执行performDraw()方法

Tips:除了上面三件事,如果LayoutParam带有权重的话,会多执行一次performMeasure()方法。

下面分别看下上面的三个方法。

performMeasure()方法
private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {
        if (mView == null) {
            return;
        }
        try {
			//调用View的onMeasure()方法
            mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
        }
    }

看下View的onMeasure()方法

  public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
        boolean optical = isLayoutModeOptical(this);
		
		...

		// 缓存的key
        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
        //初始化缓存
        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);      

        if (forceLayout || needsLayout) {
            //从缓存里面获取数据
            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
			//如果缓存没有,或者忽略缓存
            if (cacheIndex < 0 || sIgnoreMeasureCache) {
                // 调用onMeasure()方法
                onMeasure(widthMeasureSpec, heightMeasureSpec);
                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
            } else {
                long value = mMeasureCache.valueAt(cacheIndex);
                //缓存有,直接走缓存的
                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
            }

            ...
	
		//把数据放入缓存
        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
    }

到这里,我们看到执行了onMeasure()方法。
ViewRootImpl.performLayout()里面应该也会调用View.onLayout()方法吧。看下

performLayout()方法
private void performLayout(WindowManager.LayoutParams lp, int desiredWindowWidth,
            int desiredWindowHeight) {

		...

        try {
            host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());

                if (validLayoutRequesters != null) {
                    host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());

                }

            }
        } finally {
            
        }
        
		...

    }

我们发现调用View.layout()方法。

	public void layout(int l, int t, int r, int b) {

			...

            onLayout(changed, l, t, r, b);

			...

    }

最终,确实调用了View的onLayout()方法。最后,看下performDraw()方法。

performDraw()方法
 	private void performDraw() {

		...

         final boolean fullRedrawNeeded = mFullRedrawNeeded;

        mIsDrawing = true;
        try {
			//执行了draw()方法
            draw(fullRedrawNeeded);
        } finally {
            mIsDrawing = false;
        }

		...

    }

到这里,流程就是ViewRootImpl的performDraw()→draw()方法。
下面看下draw()方法。

private void draw(boolean fullRedrawNeeded) {
        Surface surface = mSurface;

		...

        mAttachInfo.mTreeObserver.dispatchOnDraw();

        	//硬件加速可用的话
            if (mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled()) {
                
				...
				
				//硬件加速可用的情况下,调用
                mAttachInfo.mThreadedRenderer.draw(mView, mAttachInfo, this);
            } else {
               
				...
				
				//硬件加速不可用的情况下,调用
                if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty)) {
                    return;
                }
            }
        

        if (animating) {
            mFullRedrawNeeded = true;
            scheduleTraversals();
        }
    }

这里,我们看下drawSoftware()方法。现在的流程有ViewRootImpl的performDraw()→draw()→drawSoftware()。

private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,
            boolean scalingRequired, Rect dirty) {

        
        final Canvas canvas;

			...

        	canvas = mSurface.lockCanvas(dirty);

				...

                mView.draw(canvas);

				...

        return true;
    }

到这里我们终于看到View的draw()。流程ViewRootImpl#performDraw()→draw()→drawSoftware()→View#draw()。

接下来看下,看下View #draw()方法。

public void draw(Canvas canvas) {
        

        /*
         *     绘制流程
         *
         *      1. 绘制背景
         *      2. 有必要的话,保存画布(绘制过的背景)
         *      3. 绘制View的内容
         *      4. 绘制子View
         *      5. 有必要的话,绘制边界。恢复画布
         *      6. 绘制滚动条等前景
         */

        // 第一步,绘制背景
        int saveCount;

        if (!dirtyOpaque) {
            drawBackground(canvas);
        }

        // 这里跳过了第二步和第五步
        final int viewFlags = mViewFlags;
        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
        if (!verticalEdges && !horizontalEdges) {
            // 第三步,绘制View的内容onDraw()。
            if (!dirtyOpaque) onDraw(canvas);

            // 第四步,绘制子View。View是空实现,ViewGroup里面会循环绘制子View
            dispatchDraw(canvas);
			
			...

            // 第六步 (前景, 滚动条)
            onDrawForeground(canvas);

            //第七步,绘制默认的焦点高亮
            drawDefaultFocusHighlight(canvas);


            // 绘制完成
            return;
        }

        /*
         * Here we do the full fledged routine...
         * (this is an uncommon case where speed matters less,
         * this is why we repeat some of the tests that have been
         * done above)
         */

        boolean drawTop = false;
        boolean drawBottom = false;
        boolean drawLeft = false;
        boolean drawRight = false;

        float topFadeStrength = 0.0f;
        float bottomFadeStrength = 0.0f;
        float leftFadeStrength = 0.0f;
        float rightFadeStrength = 0.0f;

        // 第二步,保存图层
    
        saveCount = canvas.getSaveCount();

        int solidColor = getSolidColor();
        if (solidColor == 0) {
            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;

            if (drawTop) {
                canvas.saveLayer(left, top, right, top + length, null, flags);
            }

            if (drawBottom) {
                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
            }

            if (drawLeft) {
                canvas.saveLayer(left, top, left + length, bottom, null, flags);
            }

            if (drawRight) {
                canvas.saveLayer(right - length, top, right, bottom, null, flags);
            }
        } else {
            scrollabilityCache.setFadeColor(solidColor);
        }

        // 第三步,绘制View内容
        if (!dirtyOpaque) onDraw(canvas);

        // 第四步,绘制子View
        dispatchDraw(canvas);

        // 第五步,绘制边界,恢复图层
        final Paint p = scrollabilityCache.paint;
        final Matrix matrix = scrollabilityCache.matrix;
        final Shader fade = scrollabilityCache.shader;
		//绘制边界
        if (drawTop) {
            matrix.setScale(1, fadeHeight * topFadeStrength);
            matrix.postTranslate(left, top);
            fade.setLocalMatrix(matrix);
            p.setShader(fade);
            canvas.drawRect(left, top, right, top + length, p);
        }

        if (drawBottom) {
            matrix.setScale(1, fadeHeight * bottomFadeStrength);
            matrix.postRotate(180);
            matrix.postTranslate(left, bottom);
            fade.setLocalMatrix(matrix);
            p.setShader(fade);
            canvas.drawRect(left, bottom - length, right, bottom, p);
        }

        if (drawLeft) {
            matrix.setScale(1, fadeHeight * leftFadeStrength);
            matrix.postRotate(-90);
            matrix.postTranslate(left, top);
            fade.setLocalMatrix(matrix);
            p.setShader(fade);
            canvas.drawRect(left, top, left + length, bottom, p);
        }

        if (drawRight) {
            matrix.setScale(1, fadeHeight * rightFadeStrength);
            matrix.postRotate(90);
            matrix.postTranslate(right, top);
            fade.setLocalMatrix(matrix);
            p.setShader(fade);
            canvas.drawRect(right - length, top, right, bottom, p);
        }
		//恢复图层
        canvas.restoreToCount(saveCount);

        // 第六步,绘制(前景,滚动条等)
        onDrawForeground(canvas);

    }

到这里整个ViewRootImpl的performDraw()就看完了。
这个方法主要的绘制顺序:

  1. 绘制背景
  2. 有必要的话,保存画布(绘制过的背景)
  3. 绘制View的内容
  4. 绘制子View
  5. 有必要的话,绘制边界。恢复画布
  6. 绘制滚动条等前景

ViewRootImpl的performDraw()的主要绘制流程:
ViewRootImpl#performDraw()→draw()→drawSoftware()→View#draw()→onDraw()。


6,调用Activity的makeVisible()

    void makeVisible() {
		//如果DecorView没有添加到Window上
        if (!mWindowAdded) {
            ViewManager wm = getWindowManager();
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
		//让DecorView显示
        mDecor.setVisibility(View.VISIBLE);
    }

如果,DecorView没有添加到Window上,就会执行WindowManager的addView()→ViewRootImpl的scheduleTraversals()方法。

void scheduleTraversals() {
		//如果没有执行过
        if (!mTraversalScheduled) {
			//标记为执行过
            mTraversalScheduled = true;
            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            if (!mUnbufferedInputDispatch) {
                scheduleConsumeBatchedInput();
            }
            notifyRendererOfFramePending();
            pokeDrawLockIfNeeded();
        }
    }

如果没有执行过,执行一遍添加到window,测量,摆放,绘制View的流程。最后,让DecorView显示。


到这里就分析完了,这里主要是从Window里取出DecorView,把DecorView设置成INVISBLE。然后,调用View的onMeasure(),onLayout(),onDraw()来测量View。最后,显示出来。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值