Android ViewRootImpl学习

2018-02-14  本文已影响0人  Lonelyyy

ViewRootImpl与Activity,Window,WindowManagerService的关系比较紧密,初次接触很难理解它们之间的关系
简单来说ViewRootImpl负责管理Activity的view,主要处理view的测量,布局,绘制等事务,即measure,layout和traversal

1.ViewRootImpl的创建与初始化

Activity创建的时候会走到WindowManagerGlobal的addView方法,这里面会创建一个ViewRootImpl对象

public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
       ...
        ViewRootImpl root;
        View panelParentView = null;
        synchronized (mLock) {
            ...
            root = new ViewRootImpl(view.getContext(), display);
            view.setLayoutParams(wparams);
            mViews.add(view);
            mRoots.add(root);
            mParams.add(wparams);
            try {
                root.setView(view, wparams, panelParentView);
            } catch (RuntimeException e) {
                // BadTokenException or InvalidDisplayException, clean up.
                if (index >= 0) {
                    removeViewLocked(index, true);
                }
                throw e;
            }
        }
    }

用于构造ViewRootImpl的参数view是一个DecorView对象,继续看构造函数的实现

public ViewRootImpl(Context context, Display display) {
        mContext = context;
        mWindowSession = WindowManagerGlobal.getWindowSession();
        mDisplay = display;
        mBasePackageName = context.getBasePackageName();
        mThread = Thread.currentThread();
        mLocation = new WindowLeaked(null);
        mLocation.fillInStackTrace();
        mWidth = -1;
        mHeight = -1;
        mDirty = new Rect();
        mTempRect = new Rect();
        mVisRect = new Rect();
        mWinFrame = new Rect();
        mWindow = new W(this);
        mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
        mViewVisibility = View.GONE;
        mTransparentRegion = new Region();
        mPreviousTransparentRegion = new Region();
        mFirst = true; // true for the first time the view is added
        mAdded = false;
        mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this,
                context);
        mAccessibilityManager = AccessibilityManager.getInstance(context);
        mAccessibilityManager.addAccessibilityStateChangeListener(
                mAccessibilityInteractionConnectionManager, mHandler);
        mHighContrastTextManager = new HighContrastTextManager();
        mAccessibilityManager.addHighTextContrastStateChangeListener(
                mHighContrastTextManager, mHandler);
        mViewConfiguration = ViewConfiguration.get(context);
        mDensity = context.getResources().getDisplayMetrics().densityDpi;
        mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
        mFallbackEventHandler = new PhoneFallbackEventHandler(context);
        mChoreographer = Choreographer.getInstance();
        mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
        if (!sCompatibilityDone) {
            sAlwaysAssignFocus = true;
            sCompatibilityDone = true;
        }
        loadSystemProperties();
    }

里面大部分都和窗口的参数相关,比较重要的成员有这么几个

2.requestLayout

setView方法的内容比较多,里面会执行到requestLayout(),看一下这个函数的具体实现

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

checkThread用于线程检查,继续看scheduleTraversals方法

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

变量mTraversalScheduled的存在是防止重复调用,如果当面没有正在进行布局的操作,则向Choreographer注册了一个回调,我们知道,Choreographer是负责接收vsync信号并且将其发送到各个使用的客户端,所以注册回调之后,等待vsync来了之后就可以进行相应的操作了
注册的callback类型是CALLBACK_TRAVERSAL,接收到vsync信号之后重新对view进行layout,对于ViewRootImpl来说是执行mTraversalRunnable,看一下这个runnable

final class TraversalRunnable implements Runnable {
        @Override
        public void run() {
            doTraversal();
        }
    }
void doTraversal() {
        if (mTraversalScheduled) {
            mTraversalScheduled = false;
            mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
            if (mProfile) {
                Debug.startMethodTracing("ViewAncestor");
            }
            performTraversals();
            if (mProfile) {
                Debug.stopMethodTracing();
                mProfile = false;
            }
        }
    }

可见,最终是走到了performTraversals()方法,performTraversals是view绘制的关键方法,但是这个方法比较长而且复杂,放到后面再讲

上一篇下一篇

猜你喜欢

热点阅读