Android4.0 WindowManagerService的分析

对于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又是由

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/pxgjx.html