美文网首页
Android Activity、Window、View

Android Activity、Window、View

作者: 折剑游侠 | 来源:发表于2020-01-17 13:36 被阅读0次

Activity.setContentView()已经解释了三者的关系。

Activity.attach()创建了window的实现类PhoneWindow

    final void attach(...){
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
    }

也就是说每个Activity对应到一个window实例PhoneWindow。setContentView()方法设置xml布局其实就是创建顶层布局DecorView,并按需创建ActionBar,menu,添加id为content的FrameLayout。然后通过LayoutInflater解析xml成view树,最后将View树添加到content。但是这里并没有解释view树何时绘制。上篇说到创建DecorView时调用了PhoneWindow.setContentView()将DecorView关联到window。那么问题来了,DecorView关联到window后何时绘制显示的呢?

我们都知道,Activity在onResume()时真正显示,先找到onResume()回调的地方。下面看源码细节。

ActivityThread.handleResumeActivity()

    public void handleResumeActivity(...){
    ...
    //回调onResume()
    final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
    ...
    final Activity a = r.activity
    ...
    r.window = r.activity.getWindow();
    View decor = r.window.getDecorView();
    decor.setVisibility(View.INVISIBLE);
    ViewManager wm = a.getWindowManager();
    ...
    r.activity.makeVisible();
    }

Activity.makeVisible()

    void makeVisible() {
        if (!mWindowAdded) {
            ViewManager wm = getWindowManager();
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        mDecor.setVisibility(View.VISIBLE);
    }

Activity.getWindowManager()方法返回WindowManager

    public WindowManager getWindowManager() {
        return mWindowManager;
    }

mWindowManager在Activity.attach()中初始化

    final void attach(...){
        ...
        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        mWindowManager = mWindow.getWindowManager();
    }

Window.setWindowManager()

    public void setWindowManager(WindowManager wm, IBinder appToken, String appName) {
        setWindowManager(wm, appToken, appName, false);
    }

    public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
            boolean hardwareAccelerated) {
        if (wm == null) {
            wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
        }
        //实现类WindowManagerImpl
        mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
    }

WindowManager继承自ViewManager接口

ViewManager接口方法

    public void addView(View view, ViewGroup.LayoutParams params);
    public void updateViewLayout(View view, ViewGroup.LayoutParams params);
    public void removeView(View view);

很明显WindowManager是view的直接管理者,而WindowManager实现类是WindowManagerImpl。

下面看WindowManagerImpl

    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
        mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
    }

    public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
        mGlobal.updateViewLayout(view, params);
    }

    public void removeView(View view) {
        mGlobal.removeView(view, false);
    }

内部调用WindowManagerGlobal.addView()

    public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
        if (view == null) {
            throw new IllegalArgumentException("view must not be null");
        }
        if (display == null) {
            throw new IllegalArgumentException("display must not be null");
        }
        if (!(params instanceof WindowManager.LayoutParams)) {
            throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
        }

        ViewRootImpl root;
        View panelParentView = null;

        synchronized (mLock) {
            //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);
            } catch (RuntimeException e) {
                if (index >= 0) {
                    removeViewLocked(index, true);
                }
                throw e;
            }
        }
    }

ViewRootImpl.setView()

    public void setView(...){
    ...
        requestLayout();
    ...
    }

ViewRootImpl.requestLayout()

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

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();
        }
    }

mTraversalRunnable

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

ViewRootImpl.doTraversal()

    void doTraversal() {
        if (mTraversalScheduled) {
            mTraversalScheduled = false;
            mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);

            if (mProfile) {
                Debug.startMethodTracing("ViewAncestor");
            }

            performTraversals();

            if (mProfile) {
                Debug.stopMethodTracing();
                mProfile = false;
            }
        }
    }

ViewRootImpl.performTraversals()开启绘制流程

    private void performTraversals() {
        //绘制流程
        performMeasure(...);
        performLayout(...);
        performDraw();
    }

最后总结下三者关系:每个Activity对应到一个Window实例,Window是窗口的抽象,其实现类是PhoneWindow,在Activity.attach()方法中初始化。Activity.setContentView()设置xml布局时,会创建DecorView真正的顶层布局,然后解析xml成view树添加到id为content的DecorView子view。在onResume()方法调用处,ActivityThread中Window通过WindowManager调用addview()添加DecorView,间接调用到ViewRootImpl.setView(),最终调用ViewRootImpl.performTraversals()开始绘制view树展示布局。

也就是说Window是view的管理者,通过WindowManager的三个方法addView()、updateViewLayout()、removeView()管理view,而ViewRootImpl才是真正的绘制入口。

相关文章

网友评论

      本文标题:Android Activity、Window、View

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