Window和WindowManager

1、什么是Window和WindowManager

Window是一个抽象类,表示一个窗口,Android中所有的视图都是通过Window来呈现的,不管是Activity,Dialog,Toast,它们的视图都是附加在Window上的,Window是View的直接管理者

Window的唯一子类是PhoneWindow,WindowManager是外界访问Window的入口。

Window有三种类型,分别是应用Window,子Window,系统Window,应用Window对应一个Activity,子Window不能单独存在,它需要附属在特定的父Window中,比如常见的Dialog,系统Window需要声明权限在能创建的Window,比如Toast和系统状态栏都是系统Window。

Window是分层的,每个Window都有对应的z-ordered,层级大的覆盖在层级小的Window上面,

WindowManager常用有三个方法,即添加View,更新View和删除View,这三个方法定义在ViewManager中,而WindowManager实现了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);
}

2、Window内部机制

Window是一个抽象的概念,每一个Window都对应着一个View和一个ViewRootImpl,Window和View通过ViewRootImpl来建立联系,Window并不是实际存在的,它是以View的形式存在,View才是Window存在的实体。

(1)Window的添加过程

WindowManager是一个接口,它的真正实现是WindowManagerImpl类

// WindowManagerImpl.class
@Override
public void addView(View view, ViewGroup.LayoutParams params) {
    mGlobal.addView(view, params, mDisplay, mParentWindow);
}

WindowManagerImpl将所有的操作交给了WindowManagerGlobal来实现,WindowManagerGlobal内部有几个重要列表:

private final ArrayList<View> mViews = new ArrayList<>();
private final ArrayList<ViewRootImpl> mRoots = new ArrayList<>();
private final ArrayList<ViewManager.LayoutParams> mParams = new ArrayList<>();
private final ArraySet<View> mDyingViews = new ArraySet<>();

mViews保存了所有的Window对应的View,mRoots保存了所有Window对应的ViewRootImpl,mParams保存了所有WIndow对应的布局参数,mDyingViews保存了那些正在被删除的View对象

// addView 方法
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);

mViews.add(view);
mRoots.add(root);
mParams.add(wparams);

然后通过ViewRootImpl的setView方法来更新界面和完成Window的添加过程,View的绘制过程是由ViewRootImpl来完成的,最后Window的添加请求就交给WindowManagerService处理。

(2)Window的删除过程

// WindowManagerImpl.class
@Override
public void removeView(View view) {
    mGlobal.removeView(view, false);
}

mGlobal.removeView中首先找到要删除View的索引,然后进行删除

(3)Window的更新过程

// WindowManagerImpl.class
@Override
public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
    mGlobal.updateViewLayout(view, params);
}

mGlobal.updateViewLayout首先更新View的LayoutParams,接着更新ViewRootImpl的LayoutParams,在ViewRootImpl中会通过scheduleTraversal的方法对View重新布局,包括测量,布局和重绘三大过程。

3、Window的创建过程

(1)Activity的Window创建过程

Activity的启动过程最终会由ActivityThread中的performLaunchActivity()来完成整个启动过程,在这个方法中会创建Activity实例对象,并调用它的attach方法为其关联运行中所依赖的一系列上下文环境变量,一是在attach()方法中会创建PhoneWindow

public void setContentView(int layoutResID) {
    getWindow().setContentView(layoutResID);
    initWindowDecorActionBar();
}

二是创建和初始化DecorView,将布局添加到DecorView的mContentParent中(内容栏),然后回调Activity的onContentChanged方法通知Activity视图已经发生变化

三是将添加到Window中,在Activity.handleResumeActivity中,首先调用Activity的onResume,接着调用Activity的makeVisible,在makeVisiable中,DecorView真正的完成了添加和显示过程,Activity才可以被用户看到。

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

(2)Dialog的Window创建过程

一是创建在Dialog中创建PhoneWindow

二是初始化DecorView并将Dialog的视图添加到DecorView中,通过setContentView

三是在Dialog.show方法中,将DecorView添加到Window中并显示

与Activity的Window创建过程很相似,普通Dialog有一个特殊之处是必须采用Activity的Context。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值