初探Activity启动流程--startActivity---android 30
- 1.前言
- 2.时序图
- 3.源码分析
-
- android.app.Activity.startActivity
- android.app.Instrumentation
- com.android.server.wm.ActivityTaskManagerService
- com.android.server.wm.ActivityStarter
- com.android.server.wm.RootWindowContainer
- com.android.server.wm.ActivityStack
- com.android.server.wm.ActivityStackSupervisor
- 从上面可以看到很多个ActivityItem,我分别在下面列举出来
- android.app.servertransaction.LaunchActivityItem extends ClientTransactionItem
- android.app.servertransaction.NewIntentItem extends ClientTransactionItem
- android.app.servertransaction.ActivityResultItem extends ClientTransactionItem
- android.app.servertransaction.ActivityLifecycleItem extends ClientTransactionItem-----抽象类
- android.app.servertransaction.ResumeActivityItem extends ActivityLifecycleItem
- android.app.servertransaction.PauseActivityItem extends ActivityLifecycleItem
- com.android.server.wm.ClientLifecycleManager
- android.app.servertransaction.ClientTransaction
- android.app.ClientTransactionHandler
- android.app.ActivityThread extends android.app.ClientTransactionHandler
- android.app.ContextImpl
- android.app.ActivityThread.ApplicationThread.H extend Handler
- android.app.servertransaction.TransactionExecutor
1.前言
以前看过很多别人写的Android启动流程,当然自己也跟着代码走过几遍,因为只是看看并没有做过任何到总结,所以到现在也类似没看,现在工作需要用到动态加载,所以想好好到梳理一遍,并且记录下来;
现在发现做笔记非常到重要,从大学开始到现在,我花了很多时间都在学习,看各种视频学各种语言,但是都没有以文档到形式,回顾过,记录过,所以如果有人问我学了什么,我只能说,我也不知道,所以同一个视频,我经常反复看,感觉真的很浪费时间,所以以我的亲身经历告诉大家,不要一直总是以学习(看视频,看书)的方式,也是需要输出的,不仅仅是代码的输出,文档的输出也是有必要的,当然如果能有时序图、类图、活动图等,当然是最好了,总结是真的很重要。
2.时序图
3.源码分析
android.app.Activity.startActivity
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) {
...
Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
...
}
final void performResume(boolean followedByPause, String reason) {
...
// mResumed is set by the instrumentation
mInstrumentation.callActivityOnResume(this);
...
}
android.app.Instrumentation
> @UnsupportedAppUsage
public void execStartActivities(Context who, IBinder contextThread, IBinder token, Activity target, Intent[] intents, Bundle options)
execStartActivitiesAsUser(who, contextThread, token, target, intents, options,
who.getUserId());
}
public int execStartActivitiesAsUser(Context who, IBinder contextThread, IBinder token, Activity target, Intent[] intents, Bundle options, int userId) {
//这个要注意,在后面会用到
IApplicationThread whoThread = (IApplicationThread) contextThread;
String[] resolvedTypes = new String[intents.length];
for (int i=0; i<intents.length; i++) {
intents[i].migrateExtraStreamToClipData(who);
intents[i].prepareToLeaveProcess(who);
resolvedTypes[i] = intents[i].resolveTypeIfNeeded(who.getContentResolver());
}
int result = ActivityTaskManager.getService().startActivities(whoThread,
who.getBasePackageName(), who.getAttributionTag(), intents, resolvedTypes,
token, options, userId);
checkStartActivityResult(result, intents[0]);
return result;
.....
}
/**
* Perform instantiation of an {@link Activity} object. This method is intended for use with
* unit tests, such as android.test.ActivityUnitTestCase. The activity will be useable
* locally but will be missing some of the linkages necessary for use within the system.
*
* @param clazz The Class of the desired Activity
* @param context The base context for the activity to use
* @param token The token for this activity to communicate with
* @param application The application object (if any)
* @param intent The intent that started this Activity
* @param info ActivityInfo from the manifest
* @param title The title, typically retrieved from the ActivityInfo record
* @param parent The parent Activity (if any)
* @param id The embedded Id (if any)
* @param lastNonConfigurationInstance Arbitrary object that will be
* available via {@link Activity#getLastNonConfigurationInstance()
* Activity.getLastNonConfigurationInstance()}.
* @return Returns the instantiated activity
* @throws InstantiationException
* @throws IllegalAccessException
*/
//Activity的生成 -----这个在下面会调用
public Activity newActivity(Class<?> clazz, Context context,
IBinder token, Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
Object lastNonConfigurationInstance) throws InstantiationException,
IllegalAccessException {
Activity activity = (Activity)clazz.newInstance();
ActivityThread aThread = null;
// Activity.attach expects a non-null Application Object.
if (application == null) {
application = new Application();
}
activity.attach(context, aThread, this, token, 0 /* ident */, application, intent,
info, title, parent, id,
(Activity.NonConfigurationInstances)lastNonConfigurationInstance,
new Configuration(), null /* referrer */, null /* voiceInteractor */,
null /* window */, null /* activityConfigCallback */, null /*assistToken*/);
return activity;
}
/**
* Perform calling of an activity's {@link Activity#onResume} method. The
* default implementation simply calls through to that method.
*
* @param activity The activity being resumed.
*/
public void callActivityOnResume(Activity activity) {
activity.mResumed = true;
activity.onResume();
...
}
com.android.server.wm.ActivityTaskManagerService
public final int startActivity(IApplicationThread caller, String callingPackage,String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return ***startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());***
}
private int startActivityAsUser(IApplicationThread caller, String callingPackage,@Nullable String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
assertPackageMatchesCallingUid(callingPackage);
enforceNotIsolatedCaller("startActivityAsUser");
...
// TODO: Switch to user app stacks here.
return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
.setCaller(caller)
.setCallingPackage(callingPackage)
.setCallingFeatureId(callingFeatureId)
.setResolvedType(resolvedType)
.setResultTo(resultTo)
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setStartFlags(startFlags)
.setProfilerInfo(profilerInfo)
.setActivityOptions(bOptions)
.setUserId(userId)
.execute();***
}
com.android.server.wm.ActivityStarter
/**
* Resolve necessary information according the request parameters provided earlier, and execute
* the request which begin the journey of starting an activity.
* @return The starter result.
*/
int execute() {
...
res = executeRequest(mRequest);
...
}
private int executeRequest(Request request) {
....
mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
request.voiceInteractor, startFlags, true, checkedOptions, inTask,
restrictedBgActivity, intentGrants);
if (request.outActivity != null) {
request.outActivity[0] = mLastStartActivityRecord;
}
return mLastStartActivityResult;
}
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, Task inTask,boolean restrictedBgActivity, NeededUriGrants intentGrants) {
...
result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants);
...
}
int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,int startFlags, boolean doResume, ActivityOptions options,
Task inTask, boolean restrictedBgActivity, NeededUriGrants intentGrants) {
...
mRootWindowContainer.resumeFocusedStacksTopActivities(
mTargetStack, mStartActivity, mOptions);
...
}
com.android.server.wm.RootWindowContainer
boolean resumeFocusedStacksTopActivities(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (!mStackSupervisor.readyToResume()) {