Android c/s模式分析Activity启动机制
android中大家经常要接触Activity,比如startActivity
或者在Activity的生命周期函数onResume,onPause
中做一些事情,既然Activity很重要那我们就来从源码来分析下Activity启动机制
涉及到的类
先看图
Activity启动涉及到的类.png
我以server,client,server与client桥接者三个维度对这些类进行了一个划分。
为啥是这三个维度呢?因为应用程序进程在与系统进程之间进行通信的时候其实它就是一个c/s的模式,系统进程被称为server端,应用程序进程称为client端,当然了android中进程之间的通信用的是binder机制,c与s之间进行通信需要定义一些协议,因此就出现了server与client桥接者。
那我们通过一张图来先对Activity启动有一个大概了解
c/s交互.png
从上图可知:启动一个Activity,就是client进程与server进程之间进行交互的一个过程,client进程通过ActivityManagerNative
给server进程发送启动request,server进程中的ActivityManagerService
处理完毕后通过ApplicationThread
给Client进程response
那我们就从client给server发送request, server处理request,
server给client发送response, client处理response来进行分析
client给server发送request
那我们就先找一个发起启动命令的入口activity.startActivity(intent)
方法,那我们就从这个方法入手开始分析
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
if (mParent == null) {
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());
}
}
......省略代码
}
上面代码展示activity.startActivity(intent)
方法最终是调用mInstrumentation.execStartActivity
方法来进行启动的,那我们来看这方法
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
......省略代码
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess();
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) {
}
return null;
}
上面代码中出现了ActivityManagerNative
这个类,这个类是client给server端的ActivityManagerService
发送命令的桥接者,ActivityManagerNative.getDefault() .startActivity
其实最终通过binder机制调用ActivityManagerService
的startActivity
方法
server处理request
现在client端的命令server端已经收到了,那来看下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 options) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, options,
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 options, int userId) {
enforceNotIsolatedCaller("startActivity");
userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
false, ALLOW_FULL_ONLY, "startActivity", null);
// TODO: Switch to user app stacks here.
return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, options, userId, null, null);
}
mStackSupervisor.startActivityMayWait
这行代码表明最终是调用ActivityStackSupervisor
的startActivityMayWait
方法来执行启动Activity,看代码
final 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 config,
Bundle options, int userId, IActivityContainer iContainer, TaskRecord inTask) {
......省略代码
// Don't modify the client's object!
intent = new Intent(intent);
// Collect information about the target of the Intent.
ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
profilerInfo, userId);
ActivityContainer container = (ActivityContainer)iContainer;
synchronized (mService) {
......省略代码
int res = startActivityLocked(caller, intent, resolvedType, aInfo,
voiceSession, voiceInteractor, resultTo, resultWho,
requestCode, callingPid, callingUid, callingPackage,
realCallingPid, realCallingUid, startFlags, options,
componentSpecified, null, container, inTask);
......省略代码
return res;
}
}
看下这函数
final int startActivityLocked(IApplicationThread caller,
Intent intent, String resolvedType, ActivityInfo aInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode,
int callingPid, int callingUid, String callingPackage,
int realCallingPid, int realCallingUid, int startFlags, Bundle options,
boolean componentSpecified, ActivityRecord[] outActivity, ActivityContainer container,
TaskRecord inTask) {
int err = ActivityManager.START_SUCCESS;
//调用者的进程信息
ProcessRecord callerApp = null;
if (caller != null) {
callerApp = mService.getRecordForAppLocked(caller);
......省略代码
}
.......省略代码
//启动当前activity的activity
ActivityRecord sourceRecord = null;
ActivityRecord resultRecord = null;
//同理也是启动当前activity的activity,只不过它需要当前activity把处理结果返回,即通过startActivityForResult方式启动
if (resultTo != null) {
sourceRecord = isInAnyStackLocked(resultTo);
if (DEBUG_RESULTS) Slog.v(
TAG, "Will send result to " + resultTo + " " + sourceRecord);
if (sourceRecord != null) {
if (requestCode >= 0 && !sourceRecord.finishing) {
resultRecord = sourceRecord;
}
}
}
......省略掉的代码 进行了各种异常的判断还有各种权限判断
//创建一个启动activity的记录信息
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
requestCode, componentSpecified, this, container, options);
......省略代码
/*把挂起的处理掉*/
doPendingActivityLaunchesLocked(false);
//调用该方法进行启动
err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, true, options, inTask);
if (err < 0) {
// If someone asked to have the keyguard dismissed on the next
// activity start, but we are not actually doing an activity
// switch... just dismiss the keyguard now, because we
// probably want to see whatever is behind it.
notifyActivityDrawnForKeyguard();
}
return err;
}
上面的代码做的事情有:做了各种异常判断,权限判断;同时创建了ActivityRecord
实例,该实例记录了server端启动的Activity的信息,ActivityRecord
的mToken
属性很重要;最终调用startActivityUncheckedLocked
方法,那我们来看下该方法
final int startActivityUncheckedLocked(ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
boolean doResume, Bundle options, TaskRecord inTask) {
......省略代码
/*在ActivityStack种开始启动*/
targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
if (!launchTaskBehind) {
// Don't set focus on an activity that's going to the back.
mService.setFocusedActivityLocked(r, "startedActivity");
}
return ActivityManager.START_SUCCESS;
}
该方法的代码实在是太多了,该方法主要做了以下的事情:
-
找当前正在启动的Activity的存放任务栈
-
SingleTask,SingleTop,SingleInstance启动模式进行处理
-
找到目标ActivityStack来启动Activity
targetStack.startActivityLocked
方法就是调用ActivityStack
的startActivityLocked
方法,那来看下该方法final void startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume, boolean keepCurTransition, Bundle options) {
TaskRecord rTask = r.task;
final int taskId = rTask.taskId;
......省略的代码主要是把task加入activitystack栈中if (doResume) { mStackSupervisor.resumeTopActivitiesLocked(this, r, options); }
}
该方法做的事情是:把ActivityRecord
加入TaskRecord
中;mStackSupervisor.resumeTopActivitiesLocked(this, r, options)
又到ActivityStackSupervisor
类中的resumeTopActivitiesLocked
方法来进行,那看下这方法:boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target, Bundle targetOptions) { ......省略代码 result = targetStack.resumeTopActivityLocked(target, targetOptions); ......省略代码 return result;
}
又再次调用ActivityStack
的resumeTopActivityLocked
方法,看该方法final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) { ......省略代码 boolean result = false; try { ......省略代码 result = resumeTopActivityInnerLocked(prev, options); } finally { mStackSupervisor.inResumeTopActivity = false; } return result;
}
resumeTopActivityInnerLocked(prev, options)
调用了该方法
final boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
......省略一大堆代码
mStackSupervisor.startSpecificActivityLocked(next, true, true);
return true;
}
该方法大致做了通知WindmanagerService
进行页面切换等操作,最终还是调用了ActivityStackSupervisor
类的startSpecificActivityLocked
方法来启动activity,那就来看下这方法
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);
r.task.stack.setLaunchTime(r);
if (app != null && app.thread != null) {
try {
......省略代码
//开始真正的启动一个Activity
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);
}
该方法所做的事情是:查找当前的activity的所在进程是否启动了,没启动则进行启动;否则开始启动activity;针对没启动的情况我们暂时不分析,realStartActivityLocked
方法来真正的执行启动activity任务,那来看下代码
final boolean realStartActivityLocked(ActivityRecord r,
ProcessRecord app, boolean andResume, boolean checkConfig)
throws RemoteException {
......省略一大堆代码
/*通知activitythread开始启动activity*/
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
r.compat, r.launchedFromPackage, r.task.voiceInteractor, app.repProcState,
r.icicle, r.persistentState, results, newIntents, !andResume,
mService.isNextTransitionForward(), profilerInfo);
......省略一小堆代码
return true;
}
上面的代码我们来详细的分析下:app
是一个ProcessRecord
对象,app.thread
这里的thread
就是IApplicationThread
的子类ApplicationThread
,其实这时候通过binder机制最终调用了ActivityThread
里的ApplicationThread
的scheduleLaunchActivity
方法,这时候会把intent等参数传递给client,参数中又一个很重要的参数r.appToken
它是server端的ActivityRecord
与client端的ActivityClientRecord
对应关系的一个依据
现在server已经给client发送了response
client接收response,处理response
ActivityThread
的ApplicationThread
的scheduleLaunchActivity
方法会接收server发过来的response,我们来看下代码
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state,
PersistableBundle persistentState, List<ResultInfo> pendingResults,
List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward,
ProfilerInfo profilerInfo) {
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.referrer = referrer;
r.voiceInteractor = voiceInteractor;
r.activityInfo = info;
r.compatInfo = compatInfo;
r.state = state;
r.persistentState = persistentState;
r.pendingResults = pendingResults;
r.pendingIntents = pendingNewIntents;
r.startsNotResumed = notResumed;
r.isForward = isForward;
r.profilerInfo = profilerInfo;
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);
}
上面代码很简单,最终会构造一个ActivityClientRecord
对象,该对象是client端的activity封装类,最终会通过Handler的方式来调用ActivityThread
里的handleLaunchActivity
方法,看下该方法
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
......省略代码
Activity a = performLaunchActivity(r, customIntent);
.......省略其他代码
}
调用performLaunchActivity
方法,看下该方法
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
......省略代码
Activity activity = null;
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
......省略代码
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);
......省略代码
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
//必须调用onCreate方法否则抛异常
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onCreate()");
}
......省略代码
return activity;
}
代码是在太长了,我就总结下这方法所做的事情:
- 调用
Instrumentation
的newActivity
方法构造一个Activity
实例 - 若Application没初始化,进行初始化
- 创建title,appContext等实例
- 调用
Activity
的attach
方法进行初始化 - 调用
Instrumentation
的callActivityOnCreate
方法,其实最终调用Activity
的onCreate
方法
到此为止一个Activity就被创建,并且正常调用了,剩下的代码大家感兴趣可以在自行研究,整个Activity启动机制分析到此。
总结
- 我们最终生成的Activity的实例是在client端存储着,也就是在ActivityThread的
mActivities
属性中存储着 - ActivityClientRecord是client端的activity的封装类
- ActivityRecord是server端的activity的封装类
- ActivityClientRecord与ActivityRecord之间是一一对应关系,是通过
toke
即ActivityRecord里的Token
对应起来的
下图是ActivityStackSupervisor,ActivityStack,TaskRecord,ActivityRecord之间的关系图
关系图