文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Android窗口机制

2022-06-06 13:04

关注

DecorView通过PhoneWindow与WindowManagerService通信原理图

在这里插入图片描述

每个Activity都有一个Window对象,这个对象是PhoneWindow类型的。
每个Window对象里面都维护着一个WindowManager对象。

Activity里面添加一个View是通过WindowManager的addView()方法实现的

相关关键类

WindowManagerService
高层级,系统窗口管理服务

Window
一个顶级窗口的外观和行为策略的一个抽象基类。

Window并不是真实存在的,它表示一种抽象的功能集合,View才是Android中的视图呈现形式,绘制到屏幕上的是View不是Window,但是View不能单独存在,它必需依附在Window这个抽象的概念上面,Android中需要依赖Window提供视图的有Activity,Dialog,Toast,PopupWindow,StatusBarWindow(系统状态栏),输入法窗口等,因此Activity,Dialog等都维护着一个Window对象。当我们调用Activity的setContentView()时,其实最终会调用Window的setContentView(),当我们调用Activity的findViewById()时,其实最终调用的是Window的findViewById()。
对 Window 的操作是通过 WindowManager 来完成的。

WindowManager
WindowManager是一个接口,里面常用的方法有:添加View,更新View和删除View,WindowManager继承自ViewManager,这三个方法定义在ViewManager中:

public interface ViewManager
{
    public void addView(View view, ViewGroup.LayoutParams params);
    public void updateViewLayout(View view, ViewGroup.LayoutParams params);
    public void removeView(View view);
}

WindowManagerImpl
低层次,负责与系统窗口管理服务进行操作通信,与Context进行关联。
是WindowManager的实现类,大部分工作都通过WindowManagerGlobal来实现。
WindowManagerGlobal
低层次,负责与系统窗口管理服务进行操作通信,不与Context进行关联。

ViewRootImpl
ViewRootImpl是一个视图层次结构的顶部,它实现了View与WindowManager之间所需要的协议,作为WindowManagerGlobal中大部分的内部实现,也就说WindowManagerGlobal方法最后还是大部分调用了ViewRootImpl。
类似 ApplicationThread 负责跟AMS通信一样,ViewRootImpl 的一个重要职责就是跟 WMS 通信,它通过静态变量 sWindowSession(IWindowSession实例,在WindowManagerGlobal中创建)与 WMS 进行通信。

源码分析

ActivityThread.handleResumeActivity()方法 :

  @Override
    public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward, String reason) {
    ...//其他代码
          if (a.mVisibleFromClient) {
                if (!a.mWindowAdded) {
                    a.mWindowAdded = true;
                    wm.addView(decor, l);
                } else {
                    // The activity will get a callback for this {@link LayoutParams} change
                    // earlier. However, at that time the decor will not be set (this is set
                    // in this method), so no action will be taken. This call ensures the
                    // callback occurs with the decor set.
                    a.onWindowAttributesChanged(l);
                }
            }
    ...//其他代码
 }

调用WindowManagerImpl.addView() :

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

调用WindowManagerGlobal.addView():

    public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
        ...//其他代码
            root = new ViewRootImpl(view.getContext(), display);
            view.setLayoutParams(wparams);
            mViews.add(view);
            mRoots.add(root);
            mParams.add(wparams);
            // do this last because it fires off messages to start doing things
            try {
                root.setView(view, wparams, panelParentView);
            } catch (RuntimeException e) {
                // BadTokenException or InvalidDisplayException, clean up.
                if (index >= 0) {
                    removeViewLocked(index, true);
                }
                throw e;
            }
        }
    }

调用ViewRootImpl.java的setView方法

    
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
        synchronized (this) {
         		...//其他代码
                // Schedule the first layout -before- adding to the window
                // manager, to make sure we do the relayout before receiving
                // any other events from the system.
                requestLayout(); //请求布局
                if ((mWindowAttributes.inputFeatures
                        & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
                    mInputChannel = new InputChannel();
                }
                mForceDecorViewVisibility = (mWindowAttributes.privateFlags
                        & PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY) != 0;
                try {
                    mOrigWindowType = mWindowAttributes.type;
                    mAttachInfo.mRecomputeGlobalAttributes = true;
                    collectViewAttributes();
                    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(), mWinFrame,
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel);
                } 
			    ...//其他代码
}

res = mWindowSession.addToDisplay() 调用了Session的addToDisplay()方法:

    @Override
    public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
            int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
            Rect outStableInsets, Rect outOutsets,
            DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {
        return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,
                outContentInsets, outStableInsets, outOutsets, outDisplayCutout, outInputChannel);
    }

调用mService.addWindow()方法添加Window,这个mService其实就是WindowManagerService对象,也就是说布局最终是由 WindowManagerService 来添加的。
分析到这里可以看到,ViewRootImpl是通过 mWindowSession(来自WindowManagerGlobal的sWindowSession对象)和WindowManagerService通信的。

参考:
ViewManager、ViewRootImp、WindowManagerImpl、WindowSession等详细解析
Android窗口机制(一)——Window,PhoneWindow,DecorView理解
Window窗口机制(二)——Window,WindowManager理解
Window窗口机制(三)——WindowManager,ViewRootImpl,View理解
Android 窗口机制
Android窗口机制(四)ViewRootImpl与View和WindowManager
android WindowManagerService
Window, WindowManager和WindowManagerService之间的关系

android window(三)ViewRootImpl
ViewRootImpl的独白,我不是一个View(布局篇)

ViewRootImpl源码分析事件分发

面试进阶之窗口机制

https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/core/java/android/view/Window.java
https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/core/java/android/view/WindowManagerImpl.java
https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/core/java/android/view/WindowManagerGlobal.java
https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/core/java/android/view/ViewRootImpl.java
http://androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/services/core/java/com/android/server/wm/Session.java
https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java


作者:yzpyzp


阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯