0. 总体流程
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
WindowManagerGlobal.initialize();
//step 1
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
//step 2
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
}
}
1. performLaunchActivity
1.1 performLaunchActivity
生成一个Activity对象,并调用attach方法,然后通过mInstrumentation.callActivityOnCreate间接调用Activity的onCreate方法
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
//加载这个activity
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
} catch (Exception e) {
}
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
Window window = null;
//该方法为Activity内部众多变量赋值,最重要的就是mWindow
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window);
//最终会调用Activity的onCreate方法
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
r.activity = activity;
r.stopped = true;
}
r.paused = true;
mActivities.put(r.token, r);
} catch (SuperNotCalledException e) {
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
}
return activity;
}
1.2 attach方法
该方法最重要的就是生成一个PhoneWindow对象mWindow,然后对其进行相关的设置,Window可以看成Activity中界面的抽象框架,所以有了Window之后,下一步肯定还要生成具体的View内容,即Activity的mDecor,Decor的原义是装饰,也就是说除了包含Activity实际想要显示的内容外,还必须具备所有应用程序共同的装饰部分如title,actionbar等,产生DecorView的过程是在setContentView中发起的,(流程:mInstrumentation.callActivityOnCreate->onCreate->setContentView)
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, String referrer, IVoiceInteractor voiceInteractor) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
mWindow = new PhoneWindow(this);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
mUiThread = Thread.currentThread();
mMainThread = aThread;
//setWindowManager
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();
mCurrentConfig = config;
}
1.3 setContentView
setContentView是一个中介,它将通过对应的Window对象来完成DecorView的构造;变量mContentParent是一个ViewGroup对象,用于容纳ContentView,当mContentParent为空时,说明是第一次调用setContentView,此时mDecor也必为空,因而创建installDecor创建一个DecorView;否则清理mContentParent中已经有的所有View对象;然后inflate新的内容,mContentParent就是这个由resId生成的View树的根。
@Override
public void setContentView(int layoutResID) {
if (mContentParent == null) {//如果是第一次调用这个函数的情况
installDecor();//需要首先生成mDecor对象
} else {
mContentParent.removeAllViews();
}
//根据ResId创建View对象
mLayoutInflater.inflate(layoutResID, mContentParent);
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}
1.4 installDecor
该函数主要有两个作用,生成mDecor和mContentParent
private void installDecor() {
if (mDecor == null) {
mDecor = generateDecor();
}
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);
mTitleView = (TextView)findViewById(com.android.internal.R.id.title);
if (mTitleView != null) {
mTitleView.setLayoutDirection(mDecor.getLayoutDirection());
if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {//如果设置了FEATURE_NO_TITLE
View titleContainer = findViewById(com.android.internal.R.id.title_container);
if (titleContainer != null) {
titleContainer.setVisibility(View.GONE);
} else {
mTitleView.setVisibility(View.GONE);
}
} else {
mTitleView.setText(mTitle);
}
} else {
mActionBar = (ActionBarView) findViewById(com.android.internal.R.id.action_bar);
if (mActionBar != null) {
mActionBar.setWindowCallback(getCallback());
if (mActionBar.getTitle() == null) {//如果actionbar没有设置title就是用mTitle
mActionBar.setWindowTitle(mTitle);
}
boolean splitActionBar = false;
final ActionBarContainer splitView = (ActionBarContainer) findViewById(
com.android.internal.R.id.split_action_bar);
}
}
}
}
1.5 generateDecor
DecorView继承自FrameLayout
protected DecorView generateDecor() {
return new DecorView(getContext(), -1);
}
1.6 generateLayout
取出window样式,并根据样式获取合适的layout资源,根据资源inflate一个view对象,然后把这个对象add到mDecor中,最后返回mContentParent,
protected ViewGroup generateLayout(DecorView decor) {
TypedArray a = getWindowStyle();
final Context context = getContext();
final int targetSdk = context.getApplicationInfo().targetSdkVersion;
WindowManager.LayoutParams params = getAttributes();
//关于actionbar的显示或不显示的设置
//关于背景
if (getContainer() == null) {
if (mBackgroundDrawable == null) {
if (mBackgroundResource == 0) {
mBackgroundResource = a.getResourceId(
com.android.internal.R.styleable.Window_windowBackground, 0);
}
if (mFrameResource == 0) {
mFrameResource = a.getResourceId(com.android.internal.R.styleable.Window_windowFrame, 0);
}
}
mTextColor = a.getColor(com.android.internal.R.styleable.Window_textColor, 0xFF000000);
}
int layoutResource;
int features = getLocalFeatures();
// 找到合适的LayoutRes
if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
} else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0
&& (features & (1 << FEATURE_ACTION_BAR)) == 0) {
} else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) {
} else if ((features & (1 << FEATURE_NO_TITLE)) == 0) {
} else if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) {
} else {
}
//start changing
mDecor.startChanging();
View in = mLayoutInflater.inflate(layoutResource, null);//inflate资源
//decor把in加进来
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
//finishChanging
mDecor.finishChanging();
return contentParent;
}
setContentView实际上做的工作就是把应用程序想要显示的视图加上系统策略中的其他元素(title,actionbar)合成到用户所看到的应用程序界面,需要注意的是setContentView并不把这个视图真正的显示出来(如果不调用setConentView,应用程序的界面会显示只是中间content部分为空而已)###
2.handleResumeActivity
通过performLaunchActivity,Activity内部已经完成了Window和DecorView的创建过程,可以说整棵View Tree已经生成了,只不过不为外界所知,也就是说WMS和SurfaceFlinger还不知道它的存在,所以接下来需要把它添加到WindowManagerGlobal中(mViews,mRoots,mParams),继而注册到WMS里。
2.1 handleResumeActivity
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
ActivityClientRecord r = mActivities.get(token);
//这会导致Activity的onResume被调用
r = performResumeActivity(token, clearHide, reason);
if (r != null) {
final Activity a = r.activity;
if (r.window == null && !a.mFinished && willBeVisible) {
//Activity所对应的Window对象
r.window = r.activity.getWindow();
//最外围的mDecor
View decor = r.window.getDecorView();
//先设置为不可见
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();//该方法实际放回的是WindowManagerImpl
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
//窗口类型
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
//
if (a.mVisibleFromClient && !a.mWindowAdded) {
a.mWindowAdded = true;
//首先把DecorView放到本地的全局记录中,然后再注册到WMS中
wm.addView(decor, l);//此时会调用到WindowManagerGlobal的addView方法
}
} else if (!willBeVisible) {
r.hideForNow = true;
}
} else {
try {
ActivityManagerNative.getDefault()
.finishActivity(token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
}
}
}
2.2 addView
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
//是否已经添加过,添加过的话就直接返回
int index = findViewLocked(view, false);
if (index >= 0) {
}
//为整个View生成一个配套的ViewRootImpl对象
root = new ViewRootImpl(view.getContext(), display);
//三个重要数据的更新
mViews.add(view);//记录decorView
mRoots.add(root);//记录ViewRootImpl
mParams.add(wparams);//记录布局属性
}
try {
//将View注册到WMS中的关键调用,同时这一步会把Decorview同步记录到ViewRootImpl内部的mView中
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
}
}
网友评论