博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android之Window与WIndowManager
阅读量:6851 次
发布时间:2019-06-26

本文共 5482 字,大约阅读时间需要 18 分钟。

基本概念

  • Window、PhoneWindow

顶层窗口样式和行为的抽象类, 概括了Android窗口的基本属性和基本功能。该类实例的getDecorView()方法返回的DecorView被用来作为顶层视图添加到WM中。

创建时机: ActivityThread.handleLaunchActivity ---> ActivityThread.performLaunchActivity --->Activity.attach

  • WindowManager、WindowManagerImpl、WindowManagerGlobal

WindowManager与一个特定的Display相关联

  • WindowManagerService

对系统中的所有窗口进行管理。WindowManager是运行在Application process中的, WindowManagerService是在system_server进程中运行, 两者的通信是通过中间的会话层IWindowSession来进行的。

添加一个根View到WindowManager中

{    final WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);    WindowManager.LayoutParams lp = new WindowManager.LayoutParams(                wm.getDefaultDisplay().getWidth(),wm.getDefaultDisplay().getHeight());    lp.type = WindowManager.LayoutParams.TYPE_APPLICATION;    lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;    lp.format = PixelFormat.TRANSLUCENT;    wm.addView(maskView, lp);}

相关类简化结构

public class PhoneWindow extends Window{    private DecorView mDecor;}public interface ViewManager{    public void addView(View view, ViewGroup.LayoutParams params);    public void updateViewLayout(View view, ViewGroup.LayoutParams params);    public void removeView(View view);}public interface WindowManager extends ViewManager {    public static class LayoutParams extends ViewGroup.LayoutParams{        //X position for this window        public int x;        public int y;        public int type;        public int flags;    }}public final class WindowManagerImpl implements WindowManager {    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();    private final Display mDisplay;        public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {        mGlobal.addView(view, params, mDisplay, mParentWindow);    }}public final class WindowManagerGlobal {    //表示View树的根节点    private final ArrayList
mViews = new ArrayList
(); //表示ViewRootImpl,一个根view对应一个ViewRootImpl private final ArrayList
mRoots = new ArrayList
(); //表示根view的WindowManager.LayoutParams private final ArrayList
mParams = new ArrayList
(); public void addView(View view, ViewGroup.LayoutParams params,Display display, Window parentWindow) { final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params; ... ViewRootImpl root = new ViewRootImpl(view.getContext(), display); view.setLayoutParams(wparams); mViews.add(view); mRoots.add(root); mParams.add(wparams); ... //通过ViewRootImpl来更新界面并完成Window的添加过程 root.setView(view, wparams, panelParentView); }}public final class ViewRootImpl implements ViewParent{ public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { //1、完成异步刷新请求,重绘界面 requestLayout(); ... //2、通过WindowSession最终完成window的添加过程, WindowSession内部通过WindowManagerService来实现Window的添加 int res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes, getHostVisibility(), mDisplay.getDisplayId(), mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mAttachInfo.mOutsets, mInputChannel); }}

Window的创建过程

Activity对应的PhoneWindow创建过程及添加时机

首先看下ActivityThead中的两个重要的方法:

performLaunchActivity( );       handleResumeActivity( );

创建时机:

在performLaunchActivity中,会调用activity.attach方法建立一个window。

Activity的View附属到Window上:setContentView()

添加时机:

在handleResumeActivity方法中启动activity的时候,首先会调用Activity的onResume方法,>接着调用Activity的makeVisible方法,在该方法中将主窗口加入到WindowManager中

代码如下:

void makeVisible() {    if (!mWindowAdded) {        ViewManager wm = getWindowManager();        wm.addView(mDecor, getWindow().getAttributes());//实际上是把主窗口的顶级view加入到WindowMangaer        mWindowAdded = true;    }    mDecor.setVisibility(View.VISIBLE);}

Dialog的Window创建过程

  1. 创建窗口:构造函数中

  2. 初始化DecorView并将Dialog的View添加到DecorView中:setContentView()

  3. 将DecorView添加到Window中并显示:show()

public class Dialog implements DialogInterface, ... {        Dialog(Context context,int themeResId, boolean createContextThemeWrapper) {        if (createContextThemeWrapper) {            mContext = new ContextThemeWrapper(context, themeResId);        } else {            mContext = context;        }            mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);            final Window w = new PhoneWindow(mContext);        mWindow = w;        w.setCallback(this);        w.setOnWindowDismissedCallback(this);        w.setWindowManager(mWindowManager, null, null);        w.setGravity(Gravity.CENTER);            mListenersHandler = new ListenersHandler(this);    }        public void setContentView(@LayoutRes int layoutResID) {        mWindow.setContentView(layoutResID);    }    public void show() {        mDecor = mWindow.getDecorView();        mWindowManager.addView(mDecor, l);    }}

Window添加过程

实际上是根视图的添加过程,在WindowManager层已经没有Window的概念,Window的概念存在于UI层,是对于Activity、Dialog、Toast等而言的。

  1. WindowManager.addView():调用2

  2. WindowManagerGlobal.addView():

    1. 创建ViewRootImpl

    2. 调用3

  3. ViewRootImpl.setView():

    1. requestLayout()

    2. mWindowSession.addToDisplay

总结

通过WindowManager.addView(View view, ViewGroup.LayoutParams params)可以看到:Window是一个抽象的概念,它以View的形式存在(不同于PhoneWindow,该Window是顶层View样式和行为的抽象类),但同时Activity、Dialog、Toast等又必须通过Window与View建立关联。根View一一对应ViewRootImpl,WindowManager内部通过ViewRootImpl进行Window(即根View)的添加、删除、更新,而ViewRootImpl内部通过WindowSession和WindowManagerService通信,最终WindowManagerService完成根View的添加、删除、更新。

Android中的Activity、Dialog、Toast、PopupWindow、菜单、状态栏都是通过Window来实现对应的View的,视图都对应一个Window。

从WmS的角度看,一个窗口并不是Window类,而是一个View类

参考:

转载地址:http://vdgul.baihongyu.com/

你可能感兴趣的文章
Android WebView缓存机制详解
查看>>
Linux iptables命令高级网络
查看>>
STL中mem_fun和mem_fun_ref的用法
查看>>
Mysql管理总结
查看>>
Exchange2007的规划和安装
查看>>
同步时间
查看>>
去除TFS版本控制信息
查看>>
南海区妇幼保健院HIS数据容灾备份系统项目
查看>>
思科3560交换机端口限速
查看>>
linux网络设备无法启动问题处理
查看>>
生活大爆炸系列之磨望远镜
查看>>
文档:Windows Server 2012 配置Hyper-V复制
查看>>
正则表达式
查看>>
Angular企业级开发(1)-AngularJS简介
查看>>
如何查看自己电脑系统的安装日期-Window上
查看>>
tomcat 连接数设置(转)
查看>>
Windows压缩包安装MySQL
查看>>
13040:All in All
查看>>
动态规划
查看>>
单纯形法
查看>>