最近在研究启动优化方面的知识,那么对于 Activity
的启动过程这方面的知识自然是逃不掉的,那么废话不多说,我们开始梳理。
(文中基于sdk28, 不少有代码片段的地方,可能比较枯燥,我们只要把握主要流程即可~)
1. 启动
启动包括冷启动和热启动,本篇我们主要围绕冷启动做简述。(还不清楚冷启动和热启动的区别,就自行Google哦)
2. 点击一个应用图标
当我们在手机桌面开始点击一个应用图标的时候,此时应用就启动起来了,那么背后究竟发生了什么事,我们一起来看一下:
2.1 startActivity
Activity#startActivity
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {//不传 options为null
startActivityForResult(intent, -1, options);
} else {
startActivityForResult(intent, -1);
}
}
Activity#startActivityForResult
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar = -----------//注释1
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
....
}
}
注释1处: mInstrumentation
为 Instrumentation
类型,调用了 execStartActivity
方法,其中 mMainThread.getApplicationThread()
需要我们重点关注。
mMainThread
-----> ActivityThread
类型
getApplicationThread()
返回 ApplicationThread
类型, 而 ApplicationThread
则是 ActivityThread
的一个内部类,大致如下:
class ActivityThread{
...
public ApplicationThread getApplicationThread()
{
return mAppThread;
}
private class ApplicationThread extends IApplicationThread.Stub {
.....
}
...
}
OK ,直到了 ApplicationThread
我们继续,调用了 Instrumentation.execStartActivity
我们需要点进去看一下:
2.2 Instrumentation#execStartActivity
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread; //----->注释1
...
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = ActivityManager.getService() //------->注释2
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result, intent);
...
return null;
}
注释1: 其中我们上面说的 ApplicationThread
被转化成 IApplicationThread
是一个 IBinder
类型 , 因为ApplicationThread
继承了 IApplicationThread.Stub
是不是很眼熟,类似于我们那个aidl
自动生成的那个代码,你可以认为是代理类。
接着往下,注释2: ActivityManager.getService
返回 IActivityManager
类型 ,看下面代码:
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
ServiceManager
获取到服务,其实就是我们的 ActivityManagerService
对象,它继承了IActivityManager.Stub
为具体实现类
public class ActivityManagerService extends IActivityManager.Stub..{
....
}
最终调用实际是 ActivityManagerService 的 startActiviy
方法,通过获取远程服务获取到代理类,调用了远程服务,此时由客户端进程转换到远程服务端进程。
2.3 ActivityManagerService#startActivity
ActivityManagerService
这里简称 AMS
,这里代码就比较多了,我们只看一些对流程上比较重要的方法:
@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());
}
里面可以看到又调用了 startActivityAsUser()
方法,继续走:
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,
boolean validateIncomingUser) {
...
// TODO: Switch to user app stacks here.
return mActivityStartController.obtainStarter(intent, "startActivityAsUser")
.setCaller(caller)
.setCallingPackage(callingPackage)
.setResolvedType(resolvedType)
.setResultTo(resultTo)
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setStartFlags(startFlags)
.setProfilerInfo(profilerInfo)
.setActivityOptions(bOptions)
.setMayWait(userId)
.execute();
}
只看到最后调用了一个 execute()
方法,那么看是谁的 execute()
方法, obtainStarter()
方法返回 ActivityStarter
类型的对象,那么就是它的,走进去看看:
ActivityStarter#execute
int execute() {
try {
if (mRequest.mayWait) {
return startActivityMayWait(mRequest.caller, mRequest.callingUid,
mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,
mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
mRequest.inTask, mRequest.reason,
mRequest.allowPendingRemoteAnimationRegistryLookup);
} else {
return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
mRequest.outActivity, mRequest.inTask, mRequest.reason,
mRequest.allowPendingRemoteAnimationRegistryLookup);
}
} finally {
onExecutionComplete();
}
}
这个 mRequest.mayWait
为 true
,因为前面我们在启动的时候设置了:
所以我们就可以直接看
startActivityMayWait
这个方法了。
这个方法就比较长了,我看了好长时间,看到最后方法返回 res
,自然而然就比较关注这个 res
赋值是什么,赋值我拿了出来:
private int startActivityMayWait(IApplicationThread caller, int callingUid,
String callingPackage, Intent intent, String resolvedType,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, WaitResult outResult,
Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
int userId, TaskRecord inTask, String reason,
boolean allowPendingRemoteAnimationRegistryLookup) {
....
final ActivityRecord[] outRecord = new ActivityRecord[1];
int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
allowPendingRemoteAnimationRegistryLookup);
return res;
....
}
这个 startActivity
继续调用调用:
方法里最终
return
又还是继续调用 startActivity
方法 :代码如下:
private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {
int result = START_CANCELED;
try {
mService.mWindowManager.deferSurfaceLayout();
result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, outActivity);
} finally {
// If we are not able to proceed, disassociate the activity from the task. Leaving an
// activity in an incomplete state can lead to issues, such as performing operations
// without a window container.
final ActivityStack stack = mStartActivity.getStack();
if (!ActivityManager.isStartResultSuccessful(result) && stack != null) {
stack.finishActivityLocked(mStartActivity, RESULT_CANCELED,
null /* intentResultData */, "startActivity", true /* oomAdj */);
}
mService.mWindowManager.continueSurfaceLayout();
}
postStartActivityProcessing(r, result, mTargetStack);
return result;
}
因为最后返回 result
所以我们还是看 result
的赋值, 调用了 startActivityUnchecked
方法 最后返回 START_SUCCESS
应该就是最后的方法了吧,目测感觉应该要到头了,看了一下这个方法有点长:
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {
....
//把目标栈移动到前台
reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
if (dontStart) {
topStack.mLastPausedActivity = null;
if (mDoResume) {
mSupervisor.resumeFocusedStackTopActivityLocked();//--------注释1
}
...
result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);//-------注释2
}
....
return START_SUCCESS;
}
注释1:ActivityStackSupervisor
负责将目标 Activity
放于栈顶 ;
注释2:复用或者创建新的任务栈 ;
2.4 ActivityStackSupervisor#resumeFocusedStackTopActivityLocked
boolean resumeFocusedStackTopActivityLocked() {
return resumeFocusedStackTopActivityLocked(null, null, null);
}
boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (!readyToResume()) {
return false;
}
if (targetStack != null && isFocusedStack(targetStack)) {
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
if (r == null || !r.isState(RESUMED)) {
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
} else if (r.isState(RESUMED)) {
// Kick off any lingering app transitions form the MoveTaskToFront operation.
mFocusedStack.executeAppTransition(targetOptions);
}
return false;
}
result = resumeTopActivityInnerLocked(prev, options)
这个方法就比较长,参考其它资料,里面比较重要的就是:
.....
if (next.app != null && next.app.thread != null) {
//把要启动Activity进程信息封装在一个 ClientTransaction 对象中了
final ClientTransaction transaction = ClientTransaction.obtain(next.app.thread,
next.appToken);
//如果要启动的activity已经存在,就该resume了
mStackSupervisor.scheduleResumeTopActivities();
}else{
//如果进程不存在,就要启动新的Activity
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
....
假如是第一次启动 Activity
就执行 mStackSupervisor.startSpecificActivityLocked()
方法,继续跟进去:
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
getLaunchTimeTracker().setLaunchTime(r);
if (app != null && app.thread != null) {
try {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
|| !"android".equals(r.info.packageName)) {
// Don't add this if it is a platform component that is marked
// to run in multiple processes, because this is actually
// part of the framework so doesn't make sense to track as a
// separate apk in the process.
app.addPackage(r.info.packageName, r.info.applicationInfo.longVersionCode,
mService.mProcessStats);
}
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
继续执行那就是 realStartActivityLocked()
方法:
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
....
// Create activity launch transaction. 创建启动Activity的事务
final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
r.appToken);
//回调callback 是 LaunchActivityItem
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
System.identityHashCode(r), r.info,
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
r.persistentState, results, newIntents, mService.isNextTransitionForward(),
profilerInfo));
final ActivityLifecycleItem lifecycleItem;
if (andResume) {
lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
} else {
lifecycleItem = PauseActivityItem.obtain();
}
clientTransaction.setLifecycleStateRequest(lifecycleItem);
// Schedule transaction. 最后开始执行了
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
....
}
这里可以看到生命周期的回调被封装成一个一个的 Item
,例如 : LaunchActivityItem
, ResumeActivityItem
, PauseActivityItem
光看名字也能大概猜出一点来。
这里 mService
就是 AMS
, getLifecycleManager()
获取到 ClientLifecycleManager
对象 , 调用 scheduleTransaction
方法 ;
2.5 ClientLifecycleManager#scheduleTransaction
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
final IApplicationThread client = transaction.getClient();
transaction.schedule();
if (!(client instanceof Binder)) {
// If client is not an instance of Binder - it's a remote call and at this point it is
// safe to recycle the object. All objects used for local calls will be recycled after
// the transaction is executed on client in ActivityThread.
transaction.recycle();
}
}
2.6 ClientTransaction#schedule
public void schedule() throws RemoteException {
mClient.scheduleTransaction(this);
}
mClient
是 IApplicationThread
就是 ApplicationThread
, 而 ApplicationThread
是 ActivityThread
的一个内部类,执行了 scheduleTransaction
方法。
此时你会发现,由原来的 Client
进程 ---------> AMS
进程 ,现在又回到了 客户端进程了。
Client
进程 ---------> AMS
进程 ---------> Client
进程
2.7 ActivityThread#ApplicationThread # scheduleTransaction
public final class ActivityThread extends ClientTransactionHandler {
@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
ActivityThread.this.scheduleTransaction(transaction);
}
}
因为 ActivityThread
继承了 ClientTransactionHandler
,在父类中实现了这个方法:
2.8 ClientTransactionHandler#scheduleTransaction
void scheduleTransaction(ClientTransaction transaction) {
transaction.preExecute(this);
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
终于看到点能看懂的代码了,开始切换主线程了,因为看到了 sendMessage
, 哈哈。
发送了一个 ActivityThread.H.EXECUTE_TRANSACTION
消息 ,obj
为 transaction
, 继续到 ActivityThread
中看下:
2.9 ActivityThread#mH
public final class ActivityThread extends ClientTransactionHandler{
//内部类H
class H extends Handler {
//很多消息类型,找到我们刚才发的消息类型 为159
public static final int BIND_APPLICATION = 110;
public static final int EXIT_APPLICATION = 111;
public static final int RECEIVER = 113;
public static final int EXECUTE_TRANSACTION = 159;
........
//处理消息
case EXECUTE_TRANSACTION:
final ClientTransaction transaction = (ClientTransaction) msg.obj;
mTransactionExecutor.execute(transaction);
break;
}
}
找到对应的消息类型,开始处理消息,取出之前的 ClientTransaction
, 并调用 其 execute
方法,继续跟进:
然后你会发现 在 ClientTransaction
类中并没有 execute
方法,因为前面我们说过把生命周期都封装成一个一个的 Item
了, 启动 Activity
是 LauncheActivityItem
所以我们应该去看 LaunchActivityItem
3.0 LaunchActivityItem#execute
该类继承了 ClientTransactionItem
public class LaunchActivityItem extends ClientTransactionItem {
@Override
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mIsForward,
mProfilerInfo, client);
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
}
啊哈 ,好熟悉的代码,调用 handleLaunchActivity
方法,就是 ActivityThread
中的,继续走:
3.1 ActivityThread#handleLaunchActivity
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
...
final Activity a = performLaunchActivity(r, customIntent);
....
return a;
}
3.2 ActivityThread#performLaunchActivity
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//创建ContextImpl
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
java.lang.ClassLoader cl = appContext.getClassLoader();
//根据类名反射出要启动的Activity
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);
}
//创建Application对象
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
//创建Window对象
Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
appContext.setOuterContext(activity);
//调用 attach方法
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);
//调用Activity 的 onCreate() 方法
mInstrumentation.callActivityOnCreate(activity, r.state);
}
public void callActivityOnCreate(Activity activity, Bundle icicle,
PersistableBundle persistentState) {
prePerformCreate(activity);
activity.performCreate(icicle, persistentState);
postPerformCreate(activity);
}
3.3 Activity#performCreate
final void performCreate(Bundle icicle) {
performCreate(icicle, null);
}
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
mCanEnterPictureInPicture = true;
restoreHasCurrentPermissionRequest(icicle);
if (persistentState != null) {
onCreate(icicle, persistentState); // 调用其 onCreate 方法
} else {
onCreate(icicle);
}
}
终于走到头了,看到了 onCreate()
方法,由于文章篇幅过长,总结放到下一篇,路过的朋友如果对你有帮助,能否为辛苦的糖葫芦点个赞👍再走啊~