本文以打开一个Activity后,到Activity显示后,如何确认各个窗口的大小和位置。不涉及到窗口中的每个view的布局的情况。一个Activity包含了一个PhoneWindow(window),一个Window代表一个窗口。
Activity并不负责视图控制,只是控制其生命周期和处理事件,真正控制视图的是Window。但Window的添加和显示又与生命周期息息相关。
在android系统中,一个window界面上出来Activity显示的界面外,至少还可能有如下的元素:状态栏,导航栏和输入法窗口
1 Activity回调onCreate前
Activity与Window第一次取得联系是ActivityThread的perfomLaunchActivity()调用Activity的attach()方法时,如下图:
在attach方法里,创建一个PhoneWindow对象,然后赋值给成员变量mWindow。因PhoneWindow继承自Window,接下来通过调用Window的setWindowManager,使得Window与WindowManager获得关联。
ActvityThread.performLaunchActivity
/** Core implementation of activity launch. */
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
if (localLOGV) Slog.v(
TAG, r + ": app=" + app
+ ", appName=" + app.getPackageName()
+ ", pkg=" + r.packageInfo.getPackageName()
+ ", comp=" + r.intent.getComponent().toShortString()
+ ", dir=" + r.packageInfo.getAppDir());
if (activity != null) {
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (r.overrideConfig != null) {
config.updateFrom(r.overrideConfig);
}
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
appContext.setOuterContext(activity);
//调用Activity.attach方法来建立activity -window -windowmanager的联系
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, r.configCallback);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
checkAndBlockForNetworkAccess();
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
//设置activity的状态:onCreate
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onCreate()");
}
r.activity = activity;
}
r.setState(ON_CREATE);
mActivities.put(r.token, r);
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to start activity " + component
+ ": " + e.toString(), e);
}
}
return activity;
}
Activity.attach
@UnsupportedAppUsage
7703 final void attach(Context context, ActivityThread aThread,
7704 Instrumentation instr, IBinder token, int ident,
7705 Application application, Intent intent, ActivityInfo info,
7706 CharSequence title, Activity parent, String id,
7707 NonConfigurationInstances lastNonConfigurationInstances,
7708 Configuration config, String referrer, IVoiceInteractor voiceInteractor,
7709 Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) {
7710 attachBaseContext(context);
7711
7712 mFragments.attachHost(null /*parent*/);
7713
7714 mWindow = new PhoneWindow(this, window, activityConfigCallback);//创建phoneWindow对象
7715 mWindow.setWindowControllerCallback(this);
7716 mWindow.setCallback(this);
7717 mWindow.setOnWindowDismissedCallback(this);
7718 mWindow.getLayoutInflater().setPrivateFactory(this);
7719 if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
7720 mWindow.setSoftInputMode(info.softInputMode);
7721 }
7722 if (info.uiOptions != 0) {
7723 mWindow.setUiOptions(info.uiOptions);
7724 }
//UI线程
7725 mUiThread = Thread.currentThread();
//建立window与WindowManager的关系
7750 mWindow.setWindowManager(
7751 (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
7752 mToken, mComponent.flattenToString(),
7753 (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
7754 if (mParent != null) {
7755 mWindow.setContainer(mParent.getWindow());
7756 }
7757 mWindowManager = mWindow.getWindowManager();
7758 mCurrentConfig = config;
7759
7760 mWindow.setColorMode(info.colorMode);
7761
7762 setAutofillOptions(application.getAutofillOptions());
7763 setContentCaptureOptions(application.getContentCaptureOptions());
7764 }
Window.setWindowManger:
frameworks/base/core/java/android/view/Window.java
770 public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
771 boolean hardwareAccelerated) {
772 mAppToken = appToken;
773 mAppName = appName;
774 mHardwareAccelerated = hardwareAccelerated;
775 if (wm == null) {
776 wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
777 }
778 mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
779 }
WindowManager是个接口类,它的实现是在WindowManagerImpl。WindowManagerImpl的重要方法里实质的工作又是交由WindowManagerGlobal处理。两者属于代理者模式。WindowManagerGlobal用于创建、管理、删除ViewRoot。三者关系如下:
2 Activity onCreate中调用setContentView
ActivityThread的perfomLaunchActivity在attach完成后,会调用Activity的onCreate方法。应用程序会在onCreate回调中调用setContentView为活动窗口添加布局。
Activity.setContentView