写完上一篇博客之后,花时间看了一下Binder,还是只能看个皮毛,所以,在自己没有完全掌握的情况的,我会更注重这种上层的宏观流程,而不纠结于底层细节。
我们自己写的布局是在setContentView()中开始执行的,大致流程就是,系统会根据主题什么的创建出一个最外层的ViewGroup,然后把我们的View添加进去,然后通知WmS添加ViewGroup,界面就这么出来了。
Activity的attach()方法
mWindow = PolicyManager.makeNewWindow(this);
mWindow是一个PhoneWindow对象,该Window和Activity进行了绑定。
PhoneWindow
@Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
......
if (mContentParent == null) {
installDecor();
} else {
mContentParent.removeAllViews();
}
mContentParent.addView(view, params);
......
DecorView是一个最外层布局,看一看generateLayout()方法
......
View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
......
in就是系统根据主题什么的创建出来的一个外层布局,并且给了我们一个id为
ID_ANDROID_CONTENT的父布局,我们将自己给Activity设置的View就添加到这个父布局中。
此时,我们已经将本地工作准备完毕,接着就是告知WmS将这个ViewGroup显示出来。
当我们向系统发出启动Activity的消息之后,系统经过处理之后也会回发一个消息给我们,这个消息被ApplicationThread接收,然后发一个handler消息给ActivityThread,然后执行handleLaunchActivity()
.......
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed);
......
我们都知道,Activity的onResume()方法执行表示界面已经显示出来了
handleResumeActivity()方法
if (r.activity.mVisibleFromClient) {
r.activity.makeVisible();
}
void makeVisible() {
if (!mWindowAdded) {
ViewManager wm = getWindowManager();
wm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;
}
mDecor.setVisibility(View.VISIBLE);
}
在这个方法中就是请求WmS将View添加进去。
wm.addView最终执行的是WindowManagerGlobal(全局唯一)
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);
ViewRootImpl的setView()方法
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mInputChannel);
这里的mWindow是一个W类,也是ViewRootImpl的内部类,当WmS那边添加完窗口后,会反馈一个消息,这个消息由W类接受,然后W类发送一个Handler消息给ViewRootImpl。
说到这里,有必要理清一下WindowManger,到底有几个,我们拿到的是哪个,举个例子吧,Toast与Activity是无关的吧,原因就在WindowManager身上。
先看看Activity是怎么拿的吧
@Override
public Object getSystemService(String name) {
......
if (WINDOW_SERVICE.equals(name)) {
return mWindowManager;
} else if (SEARCH_SERVICE.equals(name)) {
ensureSearchManager();
return mSearchManager;
}
return super.getSystemService(name);
}
返回的是与他绑定的Window的WindowManager.
ActivityThread的performLaunchActivity()方法:
//此时Activity对象已经创建出来
......
if (activity != null) {
//为Activity创建一个ContextImpl对象
Context appContext = createBaseContextForActivity(r, activity);
//配置Activity内部的参数
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config);
再看Activity的attach()方法
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
ContextImpl有一段静态代码块
static {
......
//这里有一堆类似的XXX_SERVICE的注册
......
registerService(WINDOW_SERVICE, new ServiceFetcher() {
Display mDefaultDisplay;
public Object getService(ContextImpl ctx) {
//搞一个Display实例
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;
}
//返回一个WindowManagerImpl实例
return new WindowManagerImpl(display);
}});
......
}
一旦执行注册,就放到缓存中了,下次你请求拿的时候就是从缓存队列中拿到的,所以,他们是全局唯一的。我们通过Activity的getSystemService()拿到的就是这里的WindowManager.
再回到Activity的onAttach()方法中的那个setWindowManager()方法
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
if (wm == null) {
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
}
//通过全局的WindowManager创建一个本地的(属于Activity)
//的localWindowManager
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
//这个parentWindow就是与Activity绑定的Window
return new WindowManagerImpl(mDisplay, parentWindow);
}
注意:在注册服务的代码中,这个parentWindow==null.