Android source code analysis - View drawing (1)

foreword

This series mainly analyzes the process related to the drawing of View, not limited to the methods Viewof , , and also includes the analysis of related classes of ,onMeasure()onLayout()onDraw()ViewRootImplVSyncChoreographer

一.ActivityThread

If you need to figure out the process, onMeasure()you need to analyze ViewRootImpl first, which is created in .onLayout()onDraw()ViewRootImplhandleResumeActivity

1.1 The handleResumeActivity method

The handleResumeActivity method is a method in the ActivityThread, which will be called after the Activity is started.

	@Override
    public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
            String reason) {
    
    
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;

		// 调用performResumeActivity,最后会调用Activity的onResume方法
		// 这里蕴含一个知识点,在onResume中无法获取View的宽高
		// 原因是onMeasure之类的方法是在ViewRootImpl里面执行的,ViewRootImpl却是在onResume调用后创建的!
        final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
        if (r == null) {
    
    
            return;
        }
        if (mActivitiesToBeDestroyed.containsKey(token)) {
    
    
            return;
        }

        final Activity a = r.activity;
		
		//...省略部分代码
		
        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) {
    
    
                if (!a.mWindowAdded) {
    
    
                    a.mWindowAdded = true;
                   	// 这里面创建了ViewRootImpl
                   	// decor是DecorView,是View树结构的根View
                    wm.addView(decor, l);
                } else {
    
    
                    a.onWindowAttributesChanged(l);
                }
            }
        } else if (!willBeVisible) {
    
    
            if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set");
            r.hideForNow = true;
        }
		//...省略部分代码
    }

ViewRootImplCreated inside wm.addView(decor, l);. Next, you need to enter WindowManagerthe code to learn.

1.2 WindowManager

The relationship diagram of ViewManager, WindowManager, WindowManagerImpl, WindowManagerGlobaland is given below . , these are interfaces, which can be regarded as proxy classes, which are the classes that actually do things. From the above figure, we can know that it is like the middleman between and , and it is created through . code show as below:ViewRootImpl
ViewManagerWindowManagerWindowManagerImplWindowManagerGlobal
window structure diagram
ViewRootImplWindowManagerViewViewRootImplWindowManagerGlobal

// WindowManagerGlobal类
public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow, int userId) {
    
    
            
            //...省略部分代码
            
            // 创建ViewRootImpl
            root = new ViewRootImpl(view.getContext(), display);

            view.setLayoutParams(wparams);

            mViews.add(view);
            mRoots.add(root);
            mParams.add(wparams);
            try {
    
    
            	// 关键点,调用ViewRootImpl的setView函数
                root.setView(view, wparams, panelParentView, userId);
            } catch (RuntimeException e) {
    
    
                // BadTokenException or InvalidDisplayException, clean up.
                if (index >= 0) {
    
    
                    removeViewLocked(index, true);
                }
                throw e;
            }          
            //...省略部分代码
}

Two. ViewRootImpl

After creating ViewRootImpl, continue to call setViewthe method:

    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView, int userId) {
    
    
	synchronized (this) {
    
    
				//...省略部分代码
				mSoftInputMode = attrs.softInputMode;
                mWindowAttributesChanged = true;
                mAttachInfo.mRootView = view;
                mAttachInfo.mScalingRequired = mTranslator != null;
                mAttachInfo.mApplicationScale =
                        mTranslator == null ? 1.0f : mTranslator.applicationScale;
                if (panelParentView != null) {
    
    
                    mAttachInfo.mPanelParentWindowToken
                            = panelParentView.getApplicationWindowToken();
                }
                mAdded = true;
                int res;
                // 在这个方法中执行绘制流程以及调整时序和接受Vsync信号
                requestLayout();
                InputChannel inputChannel = null;
                if ((mWindowAttributes.inputFeatures
                        & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
    
    
                    inputChannel = new InputChannel();
                }
                mForceDecorViewVisibility = (mWindowAttributes.privateFlags
                        & PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY) != 0;
               //...省略部分代码
	}
}

2.1 requestLayout method

	@Override
    public void requestLayout() {
    
    
        if (!mHandlingLayoutInLayoutRequest) {
    
    
            // 检测线程,看看是不是主线程
            checkThread();
            mLayoutRequested = true;
            // 和Choreographer相关的
            scheduleTraversals();
        }
    }

scheduleTraversalsIs a very important method, Choreographerrelated methods for execution.

    void scheduleTraversals() {
    
    
        if (!mTraversalScheduled) {
    
    
            mTraversalScheduled = true;
            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            notifyRendererOfFramePending();
            pokeDrawLockIfNeeded();
        }
    }

The most important thing here is Choreographerthis class, which mainly accepts the VSync signal and its related logic processing. The following chapter will make a rough analysis of this class.

Summarize

Through the above analysis, we know that ViewRootImpl is created after onResume is called, and then executes the DecorViewmethod , , so we cannot get the width and height of the View in onResume , because the View has not been measured yet.onMeasure()onLayout()onDraw()

Guess you like

Origin blog.csdn.net/RQ997832/article/details/123908194