关于Window,PhoneWindow和WindowManager三者的关系是:
Window是一个抽象类,他的具体实现是PhoneWindow
我们通过WindowManager来管理Window。
我们的所有的界面,例如Activity,Toast,Dialog等都是靠Window来呈现,因此他是View的管理者咯。
很久前用过他的一个功能就是拿来做消息提醒,当有用户发来特定消息时候,就跑出来一个小悬浮窗来提示用户。现在看得多的就是各种管家关于内存的提示!这真的很让人纠结的安卓机啊!特别是某米的手机,当年发现他不支持这个功能!搞到得单独为他开发一个别的方式….
好了,说这么多,我们该从哪里开始说起呢?
起航
API:23
我们先挑WindowManager 开始吧。
public interface WindowManager extends ViewManager
我们的WiddowManger是一个接口,不是实际干活的人,看下他继承的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
不过很有意思的是,他也是一个壳,实际干活的都交给了WindowManagerGlobal去干了。
public final class WindowManagerImpl implements WindowManager {
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mDisplay, mParentWindow);
}
@Override
public void removeView(View view) {
mGlobal.removeView(view, false);
}
@Override
public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.updateViewLayout(view, params);
}
...
}
addView
我们继续跟下,看在addView背后做了什么
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
...
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
...
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) {
...
}
}
private final ArrayList<View> mViews = new ArrayList<View>();
private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
private final ArrayList<WindowManager.LayoutParams> mParams =
new ArrayList<WindowManager.LayoutParams>();
我们看到他主要是创建了新的ViewRootImpl,然后将View,ViewRootImpl和params保存起来,最后将View添加进去ViewRootImpl里面去。这里有种感觉,removeView做的就可能和上面的相反,从数组移除,然后调用root.removeView()的类似函数去移除。这是猜测,我们先留着,看完我们的主线
我们来看下这个setView里面做了什么
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {