美文网首页
Activity与显示的关系(2)

Activity与显示的关系(2)

作者: 我叫王菜鸟 | 来源:发表于2017-10-05 18:09 被阅读0次

    简介

    回顾我们之前的调用关系

    ActivityThread.handleLaunchActivity()
        Activity a = performLaunchActivity()
            activity = mInstrumentation.newActivity()
            activity.attach()
                mWindow = new PhoneWindow(this);
                mWindow.setWindowManager((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)...);
                    mWindowManager = ((WindowManagerImpl)mContext.getSystemService("window")).createLocalWindowManager(this);
                        return new WindowManagerImpl(mDisplay, parentWindow)
                mWindowManager = mWindow.getWindowManager()
            mInstrumentation.callActivityOnCreate(activity...)
                activity.performCreate(...)
                    onCreate(...)
                        setContentView(R.id.xx)
                            getWindow().setContentView(layoutResID);
                                PhoneWindow.installDecor()
                                    generateDecor()
                                        return new DecorView();
        handleResumeActivity()
            wm.addView(decor...)
                mGlobal.addView(view...)
                    root = new ViewRootImpl(...)
                        Surface mSurface = new Surface()//成员变量
                        mWindowSession = WindowManagerGlobal.getWindowSession()
                            IWindowManager windowManager = getWindowManagerService()
                                sWindowManagerService = IWindowManager.Stub.asInterface(ServiceManager.getService("window"))
                            sWindowSession = windowManager.openSession()
                                Session session = new Session()//在WMS中
                        mWindow = new W(this)//构造函数
                    root.setView(view...)
                        mWindowSession.addToDisplay(mWindow...)
                            return mService.addWindow(...)//mService是WMS
                                token = new WindowToken(...)
                                WindowState win = new WindowState(...)
                                win.attach()
                                    mSession.windowAddedLocked();
                                        mSurfaceSession = new SurfaceSession();
                                mWindowMap.put(client.asBinder(), win)//将这个window加入列表中
                        requestLayout()
                            scheduleTraversals()
                                run(){doTraversal()}
                                    performTraversals()
    

    我们在Activity.attach()的时候:

    • Window = new PhoneWindow(this);
    • mWindow.setWindowManager((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)...);
    • mWindowManager = mWindow.getWindowManager()

    我们在onCreate()的时候:

    • new DecorView();

    我们在handleResumeActivity()的时候:

    • root = new ViewRootImpl(...)

    我们今天的核心是梳理ViewRootImpl到底干什么。

    首先我们从继承关系入手:


    image.png
       public ViewRootImpl(Context context, Display display) {
            mContext = context;
            mWindowSession = WindowManagerGlobal.getWindowSession();
            ...
            mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
        }
    

    这里最核心的就是mWindowSession,暂时也不知道这个是什么,继续往下走

    我们会发现有几个比较熟悉的方法

    • setView()
    • requestLayout()
      等方法,我们先看serView方法
        public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
            synchronized (this) {
                if (mView == null) {
                    mView = view;
    ...
    requestLayout();
    ...
                        res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                                getHostVisibility(), mDisplay.getDisplayId(),
                                mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                                mAttachInfo.mOutsets, mInputChannel);
    ...
    
    
        @Override
        public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
                int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
                Rect outOutsets, InputChannel outInputChannel) {
            return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
                    outContentInsets, outStableInsets, outOutsets, outInputChannel);
        }
    

    可知ViewRoot内部是通过通过WindowSession最终完成window的添加过程, WindowSession内部通过WindowManagerService来实现Window的添加并且通过requestLayout()来完成异步刷新请求

    并且我们这里要知道mWindow是W的对象。我们将W传递到了WMS了,我们在ViewRoot中使用mWindowSession和WMS通信。W是个Binder对象,mWindowSession是WMS中生产出来的Session对象。也是一个Binder对象,所以这里可以看出来一个问题。

    • ViewRoot用WMS的Session代理给WMS发送跨进程消息
    • WMS用ViewRoot的W对象给ViewRoot发送跨进程消息

    其实这里就不难找思路了,我们就可以看到底有那些和WMS交互的接口就好了,所以我们可以直接看Session代理接口也就是IWindowSession.aidl

    interface IWindowSession {
        int add(IWindow window, int seq, in WindowManager.LayoutParams attrs,
                in int viewVisibility, out Rect outContentInsets, out Rect outStableInsets,
                out InputChannel outInputChannel);
        int addToDisplay(IWindow window, int seq, in WindowManager.LayoutParams attrs,
                in int viewVisibility, in int layerStackId, out Rect outContentInsets,
                out Rect outStableInsets, out Rect outOutsets, out InputChannel ...
        void remove(IWindow window);
        int relayout(IWindow window, int seq, in WindowManager.LayoutParams attrs,
                int requestedWidth, int requestedHeight, int viewVisibility,
                int flags, out Rect outFrame, out Rect outOverscanInsets,
                out Rect outContentInsets, out Rect outVisibleInsets, out Rect outStableInsets,
                out Rect outOutsets, out Configuration outConfig, out Surface outSurface);
    ...
    

    提供了一些常用给窗口增加移除等接口,那就说明真正干活的是要通过WMS的某个类并不是ViewRoot。

    我们继续看requestLayout():

        @Override
        public void requestLayout() {
            if (!mHandlingLayoutInLayoutRequest) {
                checkThread();
                mLayoutRequested = true;
                scheduleTraversals();
            }
        }
    
        void checkThread() {
            if (mThread != Thread.currentThread()) {
                throw new CalledFromWrongThreadException(
                        "Only the original thread that created a view hierarchy can touch its views.");
            }
        }
    

    这个判断下是不是当前线程

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

    我们看mTraversalRunnable

    image.png

    然后就知道我们将消息post出去最后在这里执行
    我们继续看看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()这个方法。

    上面说的和上一节最后说的稍许重复,但是目的只有一个,就是最后通知完WMS之后,做了一些操作之后,执行performTraversals界面就能出来。

    总结

    • Activity的顶层Vieew是DecorView,我们经常在onCreat中使用的setContentView设置的View只不过是设置DecorView的一部分。


      image.png
    • 之所以Activity能具有显示的能力,是因为包含PhoneWindow和WindowManagerImpl而WindowManagerImpl内部有WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();WindowManagerGlobal又创建ViewRoot其中ViewRoot和WMS进行通信
    • ViewRoot,包含W的对象与mView(DecorView)对象和一个Surface mSurface = new Surface();对象并且ViewRoot具有处理Handle消息能力,最后 final TraversalRunnable mTraversalRunnable = new TraversalRunnable();通过这个处理消息performTraversals也是在这里调用
    • 在performTraversals中在Surface生产的画布上画画。

    我们下一次的流程主要沿着两点,一点是在performTraversals中大概做了什么,当然我们重点流程是显示,所以我们更要说明Surface干了什么。

    相关文章

      网友评论

          本文标题:Activity与显示的关系(2)

          本文链接:https://www.haomeiwen.com/subject/crckyxtx.html