• 【Android】ViewRootImpl、WindowManagerGlobal和WindowManager之间的关系


    前面介绍了ViewRootImplChoreographer的相互配合刷新界面:界面是如何刷新的流程

    ViewRootImpl的描述是这样的:

    The top of a view hierarchy, implementing the needed protocol between View and the WindowManager. This is for the most part an internal implementation detail of WindowManagerGlobal

    翻译一下

    View层次结构的顶部,实现视图和窗口管理器之间所需的协议。这在很大程度上是一种WindowManagerGlobal详细的内部实现

    View mView作为ViewRootImpl的一个属性,承担了所有和视图相关的操作。

    我们可以猜测 mView就是用户看到的屏幕界面。

    为了验证猜测,下面我们看一下mView是从哪里来的,是怎么添加到ViewRootImpl中的。

    绑定视图到Window

    从最熟悉的地方开始:

    #Activity
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        getWindow().setContentView(view, params);
    }
    

    Window的实现类是PhoneWindow,Decor是Activity View视图最外层的ViewGroup,由PhoneWindow创建:

    #PhoneWindow
    @Override
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        installDecor();
        mContentParent.addView(view, params);
    }
    

    Window和WindowManager的创建

    Activityattach创建了PhoneWindow的实例:

    #Activity
    final void attach() {
            mWindow = new PhoneWindow(this, window, activityConfigCallback);
            mWindow.setWindowManager(
                    (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                    mToken, mComponent.flattenToString(),
                    (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
    }
    

    PhoneWindow的父类Window设置WindowManager

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

    现在我们知道Activity创建了一个Window:PhoneWindow,PhoneWindow中有ViewGroup:Decor,还有WindowManager

    绑定View和WindowManager

    handleResumeActivity方法中,调用了WindowManageradd方法,第一个参数是decor,这个WindowManager就是上文说PhoneWindow的WindowManager:

    #ActivityThread
    @Override
    public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
            String reason) {
            
        final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
    
        final Activity a = r.activity;
    
        if (r.window == null && !a.mFinished && willBeVisible) {
            r.window = r.activity.getWindow();
            //Decor
            View decor = r.window.getDecorView();
            decor.setVisibility(View.INVISIBLE);
            //WindowManager
            ViewManager wm = a.getWindowManager();
            WindowManager.LayoutParams l = r.window.getAttributes();
            a.mDecor = decor;
    
            if (a.mVisibleFromClient) {
                if (!a.mWindowAdded) {
                    a.mWindowAdded = true;
                    //Add
                    wm.addView(decor, l);
                } else {
                    a.onWindowAttributesChanged(l);
                }
            }
        } 
    }
    

    添加view到Global

    WindowManagerImplWindowManager的实现类:

    #WindowManagerImpl
    
    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
    
    @Override
    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
        mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
                mContext.getUserId());
    }
    

    绑定WindowManagerGlobal和ViewRootImpl

    WindowManagerGlobal.addView创建了ViewRootImpl,并且设置了View

    #WindowManagerGlobal
    
    public void addView(View view, ViewGroup.LayoutParams params,
                Display display, Window parentWindow, int userId) {
    
            final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
    
            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);
    
                root.setView(view, wparams, panelParentView, userId);
                
            }
    }
    

    总结

    1. Activity创建PhoneWindow
    2. Activity设置PhoneWindow的View和WindowManager
    3. Activity Resume时,通过WindowManager添加View
    4. WindowManager实际调用的WindowManagerGlobal
    5. WindowManagerGlobal创建了ViewRootImpl,并且给ViewRootImpl设置View
  • 相关阅读:
    day28--JS(同步异步代码,回调函数地狱,promise链式调用,async函数和await,事件循环,宏任务与微任务)
    C++复习 ——内联函数
    华为认证云计算专家(HCIE-Cloud Computing)–多选题
    MyBatis-Plus--多租户插件的用法
    PHP 程序员为什么依然是外包公司的香饽饽?
    知识变现海哥|如何运营一个培训类社群
    Docker搭建私有镜像仓库及推送、拉取私服镜像
    js函数定义方式的区别
    [machine Learning]推荐系统
    机器学习的打分方程汇总
  • 原文地址:https://blog.csdn.net/qq_23049111/article/details/127104356