准备工作
分析源码前,为了方便在Android Studio查看源码,打开网址:https://github.com/anggrayudi/android-hidden-api下载对应的API源码
然后将下载的源码,替换自己SDK下对应PAI的android.jar
然后重启Android Studio之后查看android.jar后就可以查看源码
Activity启动
应用程序的入口类是ActivityThread,在ActivityThread中有performLaunchActivity来启动Activity,这个performLaunchActivity方法内部会创建一个Activity。下面查看performLaunchActivity方法:
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
····省略代码
Activity activity = null;
try {
//反射创建一个Activity
java.lang.ClassLoader cl = r.packageInfo.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 {
····省略代码
//创建PhoneWindow和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);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
if (r.isPersistable()) {
//调用Activity的onCreate方法
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
····省略代码
} 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;
}
attach方法创建PhoneWindow和WindowManager
跟随attach方法来到Activity里面查看:
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,
Window window) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
//创建PhoneWindow
mWindow = new PhoneWindow(this, window);
mWindow.setWindowControllerCallback(this);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(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);
}
mUiThread = Thread.currentThread();
mMainThread = aThread;
mInstrumentation = instr;
mToken = token;
mIdent = ident;
mApplication = application;
mIntent = intent;
mReferrer = referrer;
mComponent = intent.getComponent();
mActivityInfo = info;
mTitle = title;
mParent = parent;
mEmbeddedID = id;
mLastNonConfigurationInstances = lastNonConfigurationInstances;
if (voiceInteractor != null) {
if (lastNonConfigurationInstances != null) {
mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
} else {
mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
Looper.myLooper());
}
}
//设置WindowManager
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;
}
上面代码里有两处很重要,第一个就是创建PhoneWindow,PhoneWindow是继承Window的,PhoneWindow就是后面用于显示的载体,因为要在PhoneWindow上添加,删除,更新VIew都要通过WindowManager来操作,所以看看PhoneWindow里的setWindowManager方法,很遗憾,这个方法在父类Window里面:
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
mAppToken = appToken;
mAppName = appName;
mHardwareAccelerated = hardwareAccelerated
|| SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
if (wm == null) {
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
}
//WindowManagerImpl里创建WindowManager
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}
上面的代码里WindowManagerImpl是WindowManager 的实现类,去查看createLocalWindowManager方法创建WindowManager :
这样一来PhoneWindow就持有了WindowManager ,就可以操作view了.既然PhoneWindow也已经创建WindowManager 也有了,下面看如何添加视图.
添加视图
在ActivityThread中performLaunchActivity,方法中调用Activity的onCreate方法
Activity的onCreate中的setContentView方法跟随进去查看:
可知getWindow就是刚刚创建的PhoneWindow,跟随PhoneWindow查看setContentView
@Override
public void setContentView(int layoutResID) {
// Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
// decor, when theme attributes and the like are crystalized. Do not check the feature
// before this happens.
if (mContentParent == null) {
//1.创建DecorView,以及DecorView中的mContentParent 布局
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
getContext());
transitionTo(newScene);
} else {
//2,将layoutResID布局加载到mContentParent和上
mLayoutInflater.inflate(layoutResID, mContentParent);
}
mContentParent.requestApplyInsets();
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
//3通知视图改变回调
cb.onContentChanged();
}
mContentParentExplicitlySet = true;
}
在上面代码1中进去查看PhoneWindow中installDecor方法
可以看到1是创建DecorView,2是通过findviewById找到DecorView中的mContentParent并创建,如此一来,布局文件加载到了DecorView上面,接下来就是显示了,在显示之前发现WindowManager并没有添加到Window上
上面代码在handleLaunchActivity中1performLaunchActivity是创建Activity,2则是要将view添加到Window
上并显示,在handleResumeActivity中有如下方法:
1
利用WindowManager讲DecorView添加到Window
2
显示视图,这样view的添加和显示都清晰了.
总结
文章写得只是大致流程,没有具体到每个细节,也可能有的地方描述不正确,谢谢指出,大家一起进步.