对于Activity,在ActivityThread.java在handleLaunchActivity会调用performLaunchActivity,而performLaunchActivity则调用Activity中的attach函数,实现创建window(实际是PhoneWindow):
Activity.java
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) {
//创建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);
}
//获取WindowManager
mWindow.setWindowManager(null, mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
mWindowManager = mWindow.getWindowManager();
}
PolicyManager.java
public static Window makeNewWindow(Context context) {
//使用sPolicy来创建window
return sPolicy.makeNewWindow(context);
}
这里的sPolicy定义是:private static final IPolicy sPolicy;
那么,如何初始化?
private static final String POLICY_IMPL_CLASS_NAME =
"com.Android.internal.policy.impl.Policy";
static {
// 获取Policy这个class并实例化
try {
Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME);
sPolicy = (IPolicy)policyClass.newInstance();
}
}
再往下:
Policy.java
public class Policy implements IPolicy {
public Window makeNewWindow(Context context) {
/*可见,activity.attach中的PolicyManager.makeNewWindow(this)是新建一个PhoneWindow
*context则是Activity中实现的ContextImpl实例
*而PhoneWindow是window的子类,故而可以赋给window
*/
return new PhoneWindow(context);
}
……
}
由Policy的定义可知,Policy implement IPolicy,并且实现了它定义的接口。
/*至此,实现了创建一个PhoneWindow*/
接着Activity.attach往下:
//设置window的Callback,Activity是实现了Window.Callback的接口的
mWindow.setCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
//设置soft input mode
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
if (info.uiOptions != 0) {
mWindow.setUiOptions(info.uiOptions);
}
我们回到最初,我们说过,在ActivityThread中会在performLaunchActivity之后判断是否成功,并真正调用handleResumeActivity();
ActivityThread.java
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
ActivityClientRecord r = performResumeActivity(token, clearHide);
//这个layoutParams是在ActivityClientRecord 这里的。
WindowManager.LayoutParams l = r.window.getAttributes();
……
/*
*r是ActivityClientRecord,在performResumeActivity之前并没有将window加入到r中
*那么,activity如何创建并且是如何加入到这个activityClientRecord中的呢?
*/
if (r.window == null && !a.mFinished && willBeVisible) {
//在activity的attach函数中创建的activity的window赋给r.window
r.window = r.activity.getWindow();
//我们知道attach创建的是PhoneWindow,那PhoneWindow中DecorView如何创建的?
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
//WindowManager是ViewManager的子类
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
//将decor赋给Activity的mDecor
a.mDecor = decor;
//type的数值是1
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
//将主View(decorView)添加到WindowManager中
wm.addView(decor, l);
}
}
}
我们在Context的分析中已经分析过,WindowManager实际上初始化的是WindowManagerImpl,通过它来进行各种操作,我们转到WindowManagerImpl.java分析addView
PhoneWindow.java
是这样获取DecorView的
public final View getDecorView() {
if (mDecor == null) {
installDecor();
}
return mDecor;
}
private void installDecor() {
if (mDecor == null) {
//创建DecorView,接着往下去看如何创建DecorView,DecorView是个什么?
mDecor = generateDecor();
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
}
if (mContentParent == null) {
//这个mContentParent是干什么的?
mContentParent = generateLayout(mDecor);
}
}
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker
{
public DecorView(Context context, int featureId) {
super(context);
mFeatureId = featureId;
}
/*
*DecorView中还实现了派发key event、key快捷方式等方法
*/
public boolean dispatchKeyEvent(KeyEvent event) {
……
}
public boolean dispatchKeyShortcutEvent(KeyEvent ev) {
……
}
}
由DecorView定义我们可以知道,DecorView是一个扩张的FrameLayout,它是所有当前的Activity中View的主View
WindowManagerImpl.java
public void addView(View view, ViewGroup.LayoutParams params, CompatibilityInfoHolder cih) {
addView(view, params, cih, false);
}
private void addView(View view, ViewGroup.LayoutParams params,
CompatibilityInfoHolder cih, boolean nest) {
//这说明将DecorView添加到WindowManager必须要满足下面这个条件,否则会报异常
if (!(params instanceof WindowManager.LayoutParams)) {
throw new IllegalArgumentException(
"Params must be WindowManager.LayoutParams");
}
final WindowManager.LayoutParams wparams
= (WindowManager.LayoutParams)params;
ViewRootImpl root;
View panelParentView = null;
synchronized (this) {
//主要是查看要添加的View是否已经在mViews中了,若有就返回对应的index
int index = findViewLocked(view, false);
if (index >= 0) {
if (!nest) {
throw new IllegalStateException("View " + view
+ " has already been added to the window manager.");
}
//为什么这样,因为若添加了view到mViews,那么mRoots也对应添加
root = mRoots[index];
root.mAddNesting++;
// Update layout parameters.
view.setLayoutParams(wparams);
root.setLayoutParams(wparams, true);
return;
}
root = new ViewRootImpl(view.getContext());
//第一次添加view到mView,mViews是还没有分配空间的
if (mViews == null) {
index = 1;
mViews = new View[1];
mRoots = new ViewRootImpl[1];
mParams = new WindowManager.LayoutParams[1];
} else {
//这里奇怪的是,为什么将mViews、mRoots中内容先保存然后再拷贝一遍呢?
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--;
//这里就完成了添加View到WindowManager
mViews[index] = view;
mRoots[index] = root;
mParams[index] = wparams;
}
//这一步非常重要
root.setView(view, wparams, panelParentView);
}
ViewRootImpl.java
public ViewRootImpl(Context context) {
getWindowSession(context.getMainLooper());
//获取当前activity的线程
mThread = Thread.currentThread();
//IWindow的代理,在ViewRootImpl中创建
//这里强调一下,创建W时传入this,代指ViewRootImpl的ContextImpl,而这个ContextImpl又是由