本篇文章是基于API25源码
知识
- Activity:这个大家都熟悉,startActivity方法的真正实现在Activity中
- Instrumentation:用来辅助Activity完成启动Activity的过程
- ActivityThread(包含ApplicationThread + ApplicationThreadNative + IApplicationThread):真正启动Activity的实现都在这里
正文:
Activity.startActivity
先从入口startActivity开始罗,其实最后调用的还是
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
onResume()
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
}
可以看,最后到了startActivityForResult里面,Instrumentation隆重出场,关于它是从哪里来的,是在Activity#attach()中作为参数传进来的。
Instrumentation.execStartActivity是真正打开activity的方法
Instrumentation.execStartActivity
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
Uri referrer = target != null ? target.onProvideReferrer() : null;
try {
...省略了Intent传值和是否存在这个activity部分代码
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
可以看出,这里出现了两个关键人物(IApplicationThread,ActivityManagerNative),IApplicationThread只是一个接口,核心代码在ActivityManagerNative中,先别着急,还要再说一个方法
checkStartActivityResult:
这个方法是专门抛异常的,它会对结果进行检查,如果无法打开activity,
则抛出诸如在配置文件没有找到activity就会发生ActivityNotFoundException类似的各种异常
有兴趣的可以自己看看源码,这里没啥好说的.
接下来看看ActivityManagerNative~
ActivityManagerNative.startActivity
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeString(callingPackage);
intent.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(resultTo);
data.writeString(resultWho);
data.writeInt(requestCode);
data.writeInt(startFlags);
if (profilerInfo != null) {
data.writeInt(1);
profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
data.writeInt(0);
}
if (options != null) {
data.writeInt(1);
options.writeToParcel(data, 0);
} else {
data.writeInt(0);
}
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
int result = reply.readInt();
reply.recycle();
data.recycle();
return result;
}
看方法内部,你会发现,我擦,怎么全是binder呢,接下去呢,去哪了?这里是AIDL,实现了IActivityManager接口。
同时看IApplicationThread是继承了IInterface,你想到了啥?
在我们平时实现跨进程IPC调用的时候是不是要继承这个接口,所以我们基本可以判定ActivityManagerNative其实就是一个跨进程调用的类。
是由远端的ActivityManagerService实现startActivity
ActivityManagerService.startActivity()
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
enforceNotIsolatedCaller("startActivity");
userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, false, ALLOW_FULL_ONLY, "startActivity", null);
// TODO: Switch to user app stacks here.
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, bOptions, false, userId, null, null);
}
ActivityStarter mActivityStarter,25的源码变成了他,当然里面内容是没怎么变的.
mActivityStarter.startActivityMayWait()
看看里面写了啥,内容有点长,我直接贴关键代码
int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor,
resultTo, resultWho, requestCode, callingPid,
callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, outRecord, container,
inTask);
继续,我们在找到startActivityLocked方法,他的代码量更多,同样,我们还是找关键的来看
ActivityStarter.startActivityLocked
try {
mService.mWindowManager.deferSurfaceLayout();
err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
true, options, inTask);
} finally {
mService.mWindowManager.continueSurfaceLayout();
}
然而经过很长的代码寻找,跳转最后到了ActivityThread….方法中调用了sendMessage
sendMessage(H.LAUNCH_ACTIVITY, r);
嗯,没错里面有个handler,我直接看handleMessage 方法吧
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
}
里面还有其他msg的操作,我就不带着看,代码很长…
我们上面调用了handleLaunchActivity这个方法,接着我们在继续找这个方法,随便查看一下他的源码
handleLaunchActivity
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
…………………………
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);
…………………………
r.paused = true;
}
} else {
…………………………
}
}
我们看到performLaunchActivity返回一个Activity,之前估计我们很多都不知道Activity究竟是怎么初始化的,这回大家终于明白了吧,我们随便看一下他的源码
performLaunchActivity
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);
…………………………
try {
//创建Application
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
…………………………
if (activity != null) {
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
//调用Activity的attach方法,这个我们在前面讲的时候也多次提及
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config);
…………………………
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
// 设置主题
activity.setTheme(theme);
}
//调用Activity的OnCreate方法,
mInstrumentation.callActivityOnCreate(activity, r.state);
…………………………
if (!r.activity.mFinished) {
//调用Activity的onStart方法
activity.performStart();
r.stopped = false;
}
if (!r.activity.mFinished) {
if (r.state != null) {
//调用Activity的OnRestoreInstanceState方法
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
}
}
…………………………
return activity;
}
Activity是通过Instrumentation这个类创建的,我们可以看一下,代码非常简短
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
return (Activity)cl.loadClass(className).newInstance();
}
我们可以看到performLaunchActivity方法调用了Activity的onCreate方法和onStart方法
然后我们在看上面的handleLaunchActivity方法在调用完performLaunchActivity方法的时候又调用了handleResumeActivity方法。我们也可以顺便看一下他的源码
handleResumeActivity
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,
boolean reallyResume) {
…………………………
//调用了Activity的performResume方法,然后执行onResume方法
ActivityClientRecord r = performResumeActivity(token, clearHide);
if (r != null) {
final Activity a = r.activity;
…………………………
boolean willBeVisible = !a.mStartedActivity;
…………………………
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
wm.addView(decor, l);
}
…………………………
r.activity.mVisibleFromServer = true;
mNumVisibleActivities++;
if (r.activity.mVisibleFromClient) {
//调用Activity的makeVisible方法
r.activity.makeVisible();
}
}
…………………………
}
总结:
- Activity中最终到startActivityForResult()
- ->接着是Instrumentation出场,调用execStartActivity()和checkStartActivityResult()(这是在启动了Activity之后判断Activity是否启动成功,例如没有在AM中注册那么就会报错)
- ->这里使用AIDL发送信息如:ActivityManagerNative.getDefault().startActivity(),接受者也就是ActivityManagerService-AMS
- AMS#startActivity,然后经过经过源码几次周转到了ActivityThread
- ->ActivityThread#handleLaunchActivity()(接收内部类H的消息,ApplicationThread线程发送LAUNCH_ACTIVITY消息给H)
- ->最终在ActivityThread#performLaunchActivity()中实现Activity的启动完成了以下几件事:
- 从传入的ActivityClientRecord中获取待启动的Activity的组件信息
- 创建类加载器,使用Instrumentation#newActivity()加载Activity对象
- 调用LoadedApk.makeApplication方法尝试创建Application,由于单例所以不会重复创建。
- 创建Context的实现类ContextImpl对象,并通过Activity#attach()完成数据初始化和Context建立联系,因为Activity是Context的桥接类,
- 最后就是创建和关联window,让Window接收的事件传给Activity,在Window的创建过程中会调用ViewRootImpl的performTraversals()初始化View。
- Instrumentation#callActivityOnCreate()->Activity#performCreate()->Activity#onCreate().onCreate()中会通过Activity#setContentView()调用PhoneWindow的setContentView()更新界面。
源码很复杂,其中看着看着就会迷路了,因为有着以前搞插件化的基础,大致知道AMS的一些类是干什么的,所幸还能探索到最后…
结语:
其实startActivity,到最后还是在ActivityThread中完成的,而具体点就是拿到ClassLoader,Instrumentation去拿ClassLoader去加载一个Class,继续获取Application也是通过Classloader进行创建的,当然有的话,就不会创建。然后创建ContextImpl,他就是Context,后面在调用attach…