Android之Window与WindowManager
2016-05-21 16:28
525 查看
基本概念
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<View> mViews = new ArrayList<View>(); //表示ViewRootImpl,一个根view对应一个ViewRootImpl private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>(); //表示根view的WindowManager.LayoutParams private final ArrayList<WindowManager.LayoutParams> mParams = new ArrayList<WindowManager.LayoutParams>(); 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(); //实际上是把主窗口的顶级view加入到WindowMangaer wm.addView(mDecor, getWindow().getAttributes()); mWindowAdded = true; } mDecor.setVisibility(View.VISIBLE); }
Dialog的Window创建过程
创建窗口:构造函数中初始化DecorView并将Dialog的View添加到DecorView中:setContentView()
将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等而言的。WindowManager.addView():调用2
WindowManagerGlobal.addView():
创建ViewRootImpl
调用3
ViewRootImpl.setView():
requestLayout()
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。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories