• 【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
  • 相关阅读:
    RabbitMQ(五)交换机
    LLM 新缺陷曝光,自我纠正成功率仅 1%;苹果超 95% 产品仍在中国制造丨 RTE 开发者日报 Vol.72
    药品专利如何申请?新药的专利保护期多久?
    R3F(React Three Fiber)基础篇
    【MySQL】高性能高可用设计实战-索引篇
    web前端期末大作业 :HTML+CSS+JavaScript+Bootstrap实现响应式网站潮酷音乐网站
    在 Apache Kafka 中通过死信队列进行错误处理
    linux如何查看各个文件夹大小
    【最新计算机毕业设计】ssm基于微信小程序的高校新生报到系统
    【C语言】入门——操作符
  • 原文地址:https://blog.csdn.net/qq_23049111/article/details/127104356