您的位置:首页 > 其它

简述Activity的启动流程(界面显示)

2016-05-13 17:55 387 查看
写完上一篇博客之后,花时间看了一下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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: