一、Activity背后的Window
每个Activity都对应一个Window,Activity并不是UI真实的载体,真实载体是Activity中的Window。
Activity.java
private Window mWindow;
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config) {
// 1、创建Window
mWindow = PolicyManager.makeNewWindow(this);
mWindow.setCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
if (info.uiOptions != 0) {
mWindow.setUiOptions(info.uiOptions);
}
// 2、创建WindowManager,并将其设置到Window中
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
mWindowManager = mWindow.getWindowManager();
}
public Window getWindow() {
return mWindow;
}
在Activity实例化之后,会调用attach方法,这个方法是Activity最早的一个回调方法,可以看到在这个里面对Window进行了创建。
PolicyManager.java
public final class PolicyManager {
private static final String POLICY_IMPL_CLASS_NAME =
"com.android.internal.policy.impl.Policy";
private static final IPolicy sPolicy;
static {
Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME);
sPolicy = (IPolicy)policyClass.newInstance();
}
public static Window makeNewWindow(Context context) {
return sPolicy.makeNewWindow(context);
}
}
public class Policy implements IPolicy {
private static final String TAG = "PhonePolicy";
public Window makeNewWindow(Context context) {
return new PhoneWindow(context);
}
}
可以看到,创建的是一个PhoneWindow实例,Window是一个抽象类,PhoneWindow继承了Window类。
既然Window是UI的载体,那么我们通常在Activity中执行setContentView方法,莫非真实执行是在Window里面,没错,你猜对了,下面我们来看看。
public void setContentView(int layoutResID) {
getWindow().setContentView(layoutResID);
initActionBar();
}
哈哈,看到没有,getWindow方法返回的就是前面创建的PhoneWindow对象,所以,setContentView的真正执行者其实是Window对象。
下面看看PhoneWindow的setContentView方法。
@Override
public void setContentView(int layoutResID) {
if (mContentParent == null) {
installDecor();
} else {
mContentParent.removeAllViews();
}
mLayoutInflater.inflate(layoutResID, mContentParent);
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}
这个其实创建一个DecorView,DecorView是一个ViewGroup,然后将我们的View添加到这个DecorView中。
二、Window的大管家WindowManager
在Window的身边,有一个得力的管家就是WindowManager,它帮助Window完成各项显示操作。WindowManager的实例化也在Activity的attach方法中。
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config) {
// 1、创建Window
mWindow = PolicyManager.makeNewWindow(this);
mWindow.setCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
if (info.uiOptions != 0) {
mWindow.setUiOptions(info.uiOptions);
}
// 2、创建WindowManager,并将其设置到Window中
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
mWindowManager = mWindow.getWindowManager();
}
在第二步中,我们看到通过context.getSystemService(Context.WINDOW_SERVICE)获取到WindowManager对象,然后及其设置到Window对象中,从而实现对Window的管理。
ContextImpl.java
@Override
public Object getSystemService(String name) {
ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
return fetcher == null ? null : fetcher.getService(this);
}
从SYSTEM_SERVICE_MAP这个Map中来获取服务代理对象,并且在这之前会将各类服务注册进去。
private static void registerService(String serviceName, ServiceFetcher fetcher) {
if (!(fetcher instanceof StaticServiceFetcher)) {
fetcher.mContextCacheIndex = sNextPerContextServiceCacheIndex++;
}
SYSTEM_SERVICE_MAP.put(serviceName, fetcher);
}
上面是注册方法,下面具体看看WindowService的注册过程
registerService(WINDOW_SERVICE, new ServiceFetcher() {
Display mDefaultDisplay;
public Object getService(ContextImpl ctx) {
Display display = ctx.mDisplay;
if (display == null) {
if (mDefaultDisplay == null) {
DisplayManager dm = (DisplayManager)ctx.getOuterContext().
getSystemService(Context.DISPLAY_SERVICE);
mDefaultDisplay = dm.getDisplay(Display.DEFAULT_DISPLAY);
}
display = mDefaultDisplay;
}
return new WindowManagerImpl(display);
}});
可以看到,我们通过的使用getSystemService(Context.WINDOW_SERVICE)获取得到的是一个WindowManagerImpl对象,并且它并不是一个真正的WindowManagerService的远程代理对象,而是一个对DisplayManagerService远程代理对象的封装。具体可以参考文章 Android WindowManagerService解析(1)
弄清了这个WindowManager之后,我们回过头去看看Window的setWindowManager的过程。
Window.java
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
mAppToken = appToken;
mAppName = appName;
mHardwareAccelerated = hardwareAccelerated
|| SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
if (wm == null) {
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
}
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}
可以看到,Window中的mWindowManager并且直接使用的前面创建一个WindowManagerImpl对象,而是通过WindowManagerImpl调用createLocalWindowManager来创建的一个WindowManagerImpl对象。
WindowManagerImpl
public final class WindowManagerImpl implements WindowManager {
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
return new WindowManagerImpl(mDisplay, parentWindow);
}
}
可以看到,它就是重新创建了一个WindowManagerImpl对象。从这里我们可以知道,在Window中的WindowManager管家是一个WindowManagerImpl对象。
三、UI的显示过程
Window仅仅只是一个载体,真正的显示是由WindowManager来处理的。
下面来看看ActivityThread的handleResumeActivity方法。
ActivityThread.java
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,
boolean reallyResume) {
ActivityClientRecord r = performResumeActivity(token, clearHide);
if (r != null) {
// 1、获取Activity对象
final Activity a = r.activity;
// 2、得到Activity的Window对象
r.window = r.activity.getWindow();
// 3、拿到Window中的decorView对象
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
// 4、拿到WindowManager对象
ViewManager wm = a.getWindowManager();
// 5、得到WindowManger的布局属性
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
// 6、调用WindowManager的addView方法
wm.addView(decor, l);
}
}
看到这里是不是很熟悉,我们平时在使用WindowManager的时候也是这样使用的,这里我们就突然明白原来Activity内部就是封装了一个windowManager,真正使用的还是它的addView方法,这个我们在使用WindowManager经常使用。