在博客《WindowManager杂谈》和《关于PopupWindow的简单说明》这两篇博客中简单的说明了一下WindowManger的创建过程以及WindowManager在PopupWindow的是如何使用的。详细看参考上述的两篇博客。我们知道,在实际开发中可以通过如下一行代码获取WindowManager对象:
(WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)
很简单,通过Context对象的getSystemServcie方法来获取的,关于该方法的详细实现原理读过《 getSystemService的简单说明 》就可以知道WindowManager是在如下的代码里面得到了注册和初始化:
registerService(WINDOW_SERVICE, new ServiceFetcher() {
public Object getService(ContextImpl ctx) {
return WindowManagerImpl.getDefault(ctx.mPackageInfo.mCompatibilityInfo);
}});
通过上面的这段代码就引申出了本篇博客要讲解的主角:WindowManagerImpl,它的getDefault方法返回了WindowManager对象,下面就让我们看看这个方法里面都做了什么(WindowManagerImpl在android.view目录下):
public static WindowManager getDefault(CompatibilityInfo compatInfo) {
CompatibilityInfoHolder cih = new CompatibilityInfoHolder();
cih.set(compatInfo);
if (cih.getIfNeeded() == null) {
return sWindowManager;
}
synchronized (sLock) {
// NOTE: It would be cleaner to move the implementation of
// WindowManagerImpl into a static inner class, and have this
// public impl just call into that. Then we can make multiple
// instances of WindowManagerImpl for compat mode rather than
// having to make wrappers.
WindowManager wm = sCompatWindowManagers.get(compatInfo);
if (wm == null) {
wm = new CompatModeWrapper(sWindowManager, cih);
sCompatWindowManagers.put(compatInfo, wm);
}
return wm;
}
}
private final static WindowManagerImpl sWindowManager = new WindowManagerImpl();
。CompatModeWrapper是WindowManagerImpl里面的静态内部类,该内部类实现了WindowManager这个接口:
static class CompatModeWrapper implements WindowManager {
private final WindowManagerImpl mWindowManager;
private final Display mDefaultDisplay;
private final CompatibilityInfoHolder mCompatibilityInfo;
}
看看CompatModeWrapper这个类即实现了WIndowManager这个接口又包含了一二WindowManagerImpl类型的对象。事实上WindowManager这个接口提供的一些方法,诸如addView,updateViewLayout,removeView等操作在CompatModeWrapper类里面还是直接由mWindowManager这个WindwoManagerImpl对象来完成的:
//CompatModeWrapper类的部分代码
@Override
public void addView(View view, android.view.ViewGroup.LayoutParams params) {
mWindowManager.addView(view, params, mCompatibilityInfo);
}
@Override
public void removeView(View view) {
mWindowManager.removeView(view);
}
@Override
public void removeViewImmediate(View view) {
mWindowManager.removeViewImmediate(view);
}
private void addView(View view, ViewGroup.LayoutParams params,
CompatibilityInfoHolder cih, boolean nest) {
......
ViewRootImpl root;
View panelParentView = null;
synchronized (this) {
。。。。。。
int index = findViewLocked(view, false);
if (index >= 0) {
if (!nest) {
throw new IllegalStateException("View " + view
+ " has already been added to the window manager.");
}
root = mRoots[index];
root.mAddNesting++;
// Update layout parameters.
view.setLayoutParams(wparams);
root.setLayoutParams(wparams, true);
return;
}
。。。。。。。
root = new ViewRootImpl(view.getContext());
view.setLayoutParams(wparams);
if (mViews == null) {
index = 1;
mViews = new View[1];
mRoots = new ViewRootImpl[1];
mParams = new WindowManager.LayoutParams[1];
} else {
index = mViews.length + 1;
Object[] old = mViews;
mViews = new View[index];
System.arraycopy(old, 0, mViews, 0, index-1);
old = mRoots;
mRoots = new ViewRootImpl[index];
System.arraycopy(old, 0, mRoots, 0, index-1);
old = mParams;
mParams = new WindowManager.LayoutParams[index];
System.arraycopy(old, 0, mParams, 0, index-1);
}
index--;
mViews[index] = view;
//将rootImpl对象添加到数组中
mRoots[index] = root;
mParams[index] = wparams;
}
// do this last because it fires off messages to start doing things
//最终调用了setView方法将View显示到手机窗口中
root.setView(view, wparams, panelParentView);
}
final class ViewRootImpl implements ViewParent,View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks
当然有的书上说ViewRootImpl是一个Handler也不错,因为在android的一个版本中,ViewRootImpl的类结构是如下所示:
final class ViewRootImpl extends Handler implements ViewParent, View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
if (mView == null) {
mView = view;
......
mAdded = true;
......
//请求布局
requestLayout();
.....
res = sWindowSession.add(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mAttachInfo.mContentInsets,
mInputChannel);
}
}
}
public static IWindowSession getWindowSession(Looper mainLooper) {
synchronized (mStaticInit) {
if (!mInitialized) {
try {
InputMethodManager imm = InputMethodManager.getInstance(mainLooper);
//获取一个IWindowManager
IWindowManager windowManager = Display.getWindowManager();
//通过IWindowManager来获取一个IWindowSession对象
sWindowSession = windowManager.openSession(
imm.getClient(), imm.getInputContext());
float animatorScale = windowManager.getAnimationScale(2);
ValueAnimator.setDurationScale(animatorScale);
mInitialized = true;
} catch (RemoteException e) {
}
}
return sWindowSession;
}
}
上面的代码主要做了两个工作:1.通过Display的getWindowManager()方法获取一个IWindowManager对象(注:IWindowManager其实是一个aidl接口,关于aidl接口的工作方式涉及到IBinder机制,这点可以参考《Android开发艺术探索》这本书具体了解一下)。2通过IWindowManger创建了一个Session.getWindowManager的具体实现如下:
static IWindowManager getWindowManager() {
synchronized (sStaticInit) {
if (sWindowManager == null) {
sWindowManager = IWindowManager.Stub.asInterface(
ServiceManager.getService("window"));
}
return sWindowManager;
}
}
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return getIServiceManager().getService(name);
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
getWindowManager函数先通过ServcieManager.getServie获取一个IBinder对象,然后将通过IWindowManager.Stub类是我asInterface函数,将IBinder对象转换成IWindowManager对象。其实分析到这儿已经分析到了Android各种书籍上所说的Framework与WMS之间的桥梁---Binder机制,
从Android FrameWork的角度来IBindershi ServiceManager链接各种manager(ActivityManager,WindowManager)和相应的ManagerServcie的桥梁(此句摘自《Android开发艺术探索》,关于IBinder的工作机制也可以参考此书进行深入的了解)。
写到这儿WinManagerImpl的简单工作原理算是简单的梳理了一遍,因为博主水平有限,IBinder的工作机制不是很了解,只能分析到这人了,具体深入的分析还有待学习