之前对于启动Activity有所了解,但是自觉了解不深,而且很容易忘记,本着"好记性不如烂笔头“这里记录下启动流程。本文章参考Android Open Source Project
在启动Activity的时候,无论是点击桌面的图标,还是自己写的App中启动Activity,最后都是归结到Activity的startActivityForResult方法。其实点击桌面的图标,也是依靠Launcher程序去打开Activity的,和我们使用startActivity方法去启动Activity是没有任何区别的。
frameworks\base\core\java\android\app\Activity.java
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
// 注意getApplicationThread方法
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) {
// If this start is requesting a result, we can avoid making
// the activity visible until the result is received. Setting
// this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
// activity hidden during this time, to avoid flickering.
// This can only be done when a result is requested because
// that guarantees we will get information back when the
// activity is finished, no matter what happens to it.
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
// TODO Consider clearing/flushing other event sources and events for child windows.
} else {
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
// Note we want to go through this method for compatibility with
// existing applications that may have overridden it.
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
无论如何startActivity,最后调用的是startActivityForResult方法。该方法最后调用了Instrumentation的execStartActivity方法。注意这句代码:
mMainThread.getApplicationThread()
mMainThread实际上是ActivityThread类,而这个类就是传说中的”主线程“。那么getApplicationThread的值是什么呢?通过系统源码可以得知它是ActivityThread的内部类ApplicationThread
frameworks\base\core\java\android\app\ActivityThread.java
@UnsupportedAppUsage
public ApplicationThread getApplicationThread()
{
return mAppThread;
}
ApplicationThread类继承了IApplicationThread.Stub,熟悉AIDL的都知道,这个类是Android通过IApplicationThread.aidl自己生成的的类。
部分ApplicationThread代码:
frameworks\base\core\java\android\app\ActivityThread.java
//...省略部分代码
private class ApplicationThread extends IApplicationThread.Stub {
private static final String DB_INFO_FORMAT = " %8s %8s %14s %14s %s";
public final void scheduleSleeping(IBinder token, boolean sleeping) {
sendMessage(H.SLEEPING, token, sleeping ? 1 : 0);
}
public final void scheduleReceiver(Intent intent, ActivityInfo info,
CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
boolean sync, int sendingUser, int processState) {
updateProcessState(processState, false);
ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
sync, false, mAppThread.asBinder(), sendingUser);
r.info = info;
r.compatInfo = compatInfo;
sendMessage(H.RECEIVER, r);
}
public final void scheduleCreateBackupAgent(ApplicationInfo app,
CompatibilityInfo compatInfo, int backupMode, int userId) {
CreateBackupAgentData d = new CreateBackupAgentData();
d.appInfo = app;
d.compatInfo = compatInfo;
d.backupMode = backupMode;
d.userId = userId;
sendMessage(H.CREATE_BACKUP_AGENT, d);
}
//...省略部分代码
而IApplicationThread.aidl恰恰是ActivityManagerService和App通讯的桥梁,后面的文章将会谈到,顺便一提,老版本用的是ActivityManagerService,新版本改为ActivityTaskManagerService。
这里的Instrumentation对象和ActivityThread对象都是通过Activity的attach方法获取到的,Instrumentation对象是每创建一个Activity都会提供一个引用。
frameworks\base\core\java\android\app\ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//...省略部分代码
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);
}
}
//...省略部分代码
if (activity != null) {
//...省略部分代码
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,
r.assistToken);
//...省略部分代码
}
}
frameworks\base\core\java\android\app\Activity.java
// 注意Instrumentation instr和IBinder token
// IBinder token就是IApplicationThread
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, ActivityConfigCallback activityConfigCallback) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
mWindow = new PhoneWindow(this, window, activityConfigCallback);
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());
}
}
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;
mWindow.setColorMode(info.colorMode);
setAutofillCompatibilityEnabled(application.isAutofillCompatibilityEnabled());
enableAutofillCompatibilityIfNeeded();
}
attach方法向Activity里面添加了很多重要的参数,比如Context,ActivityThread,application等等。至于attach何时被执行,后面的文章将会给出详细的分析。
下一篇:Activity启动源码分析-基于Android10(二)
参考文章:Activity的启动流程-基于Android10源码