ViewRootImpl入門

4579 ワード

きそ


それ自体はごく普通のクラスです(初期のViewRootImplはHandlerだったそうですがapi 23ではそうではありません).
Activity#handleResumeActivity()では、Activityに関連付けられたPhoneWindowオブジェクトのDecorViewがViewRootImpl#setView()に渡されます.一方、ViewRootImplによって測定、レイアウト、描画が行われるとともに、ViewRootImplはWMSと複雑に対話し、ActivityのUIを示す.まとめると、その役割は次のとおりです.
1は、Activity#setContentView()で生成されたぺこぺこしたViewツリーを、Viewに塗りつぶします.
2,WMSとコミュニケーションをとり,表示するインタフェースを管理する.

コンストラクタ


        ActivityThread#handleResumeActivity()->WindowManagerImpl#addView()->WindowManagerGlobal#addView()->ViewRootImpl(view.getContext(),Display).
コンストラクション関数では、ViewRootImplのグローバル変数mContextに最初のパラメータが割り当てられます.handleResumeActivityによって伝達するViewオブジェクトはWindow#mDecorであるのでview.getContext()は、DecorViewが指すActivityインスタンスを返します.
一部のコンストラクション関数のコードは次のとおりです.
        mWindowSession = WindowManagerGlobal.getWindowSession();
        mWindow = new W(this);
        mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this);

最初の文mWindowSessionはWindowManagerGlobalに割り当てられています.getWindowSession()は、値が1つのSessionオブジェクトであることを返し、Sessionのインスタンス化はWMSプロセスで行われ、本来は1つのSessionのエージェントオブジェクトがあるはずなので、Sessionによって主にWMSのいくつかのメソッドを呼び出すことができます.
第二、三句中のWはIWindowに継承する.Stubは,後者がBinderに継承され,IWindowインタフェースが実現されるため,このWはIPC可能である.3番目の文ではmWindowをViewに割り当てた.AttachInfoのmWindowオブジェクトは、mWindowSession変数にmWindowSessionを割り当てます.

setView


コンストラクション関数呼び出しタイミングと同じであり、Viewパラメータも同じである.したがって、ViewRootImplのmViewとは、このViewRootImplが依存するActivityのDecorViewを指す.したがって、mViewを呼び出すことで、ActivityコンポーネントのUIを描画することができます.
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
        synchronized (this) {
            if (mView == null) {
                mView = view;
                // 
                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);
                } 
                // 
            }
        }
    }

一方、requestLayout->scheduleTraversals()->Choreographer#postCallback()->postCallbackDelayedInternal()->scheduleFrameLocked()->scheduleFrameLocked()->scheduleFrameLocked()は、MSG_DO_FRAMEのmsg->doFrame()です.この過程でscheduleTransversals()のパラメータを追跡する必要があり,postCallbackDelayedInternal()までは正常に伝達されていた.postCallbackDelayedInternal()は次のとおりです.
    private void postCallbackDelayedInternal(int callbackType,
            Object action, Object token, long delayMillis) {// scheduleTraversals() ,token Null,delayMills 0
        synchronized (mLock) {
            final long now = SystemClock.uptimeMillis();
            final long dueTime = now + delayMillis;
            mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);
            // CallbackRecord , 
            if (dueTime <= now) {// delayMills 0, 
                scheduleFrameLocked(now);
            } else {
                Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
                msg.arg1 = callbackType;
                msg.setAsynchronous(true);
                mHandler.sendMessageAtTime(msg, dueTime);
            }
        }
    }

doFrame()に着いたとき、こんな言葉がありました.
            doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);

最初のパラメータはscheduleTransversals()の最初のパラメータであり、doCallBacks()ではCallbackRecord#run()が呼び出されます.
        public void run(long frameTimeNanos) {
            if (token == FRAME_CALLBACK_TOKEN) {
                ((FrameCallback)action).doFrame(frameTimeNanos);
            } else {
                ((Runnable)action).run();
            }
        }

したがって、ここではscheduleTransversals()の2番目のパラメータが実行されます.2番目のパラメータ->doTraversal()->performTraversals()は、このメソッドではViewのmeasure、layout、drawが実行されます.
ここでrequestLayout()メソッドは実行され、その役割はViewツリーを測定し、レイアウトし、描画することです.setView()では、mWindowSession#addToDisplay()も呼び出されます.mWindowSessionは、WMSによって作成されたSessionオブジェクトが本アプリケーションのエージェントであるため、mWindowSession#addToDisplay()は、WMSが存在するプロセスに実行されます.Sessionではこの方法は簡単で、パラメータ(thisはSessionオブジェクト自体を指す)を追加してWMS#addWindow()に渡すだけです.