Android Activity 启动流程分析_android activity工作流程

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注Android)
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

正文

这篇文章主要来看一下应用内启动 Activity 是一个怎样的流程

一,Activity -> ATMS

众所周知,一般情况下Activity 的启动方式有下面种:

  • startActivity(Intent intent):直接启动一个 Activity
  • startActivityForResult(Intent intent, int requestCode):带返回值的启动方式,这种启动方式已经被官方所废弃,取而代之的是 registerForActivityResult(contract, mActivityResultRegistry, callback)

我们从 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 {
startActivityForResult(intent, -1);
}
}

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
startActivityForResult(intent, requestCode, null);
}

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {

//execStartActivity
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());
}

} else {
if (options != null) {
//这里最终也是调用 execStartActivity 方法
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}

上面代码中,调用了 execStartActivity 方法,该方法会返回一个启动结果。最下面的的 startActivityFromChild 方法最终也是调用的 execStartActivity。

我们先看一下该方法的参数:

public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
}

  1. Context who :传入的是 this,用来启动 Activity 的对象
  2. Ibinder contextThread:Binder 对象,具有跨进程通信的能力,传入的是 mMainThread.getApplicationThread()

public ApplicationThread getApplicationThread(){
return mAppThread;
}
final ApplicationThread mAppThread = new ApplicationThread();

private class ApplicationThread extends IApplicationThread.Stub {

}

ApplicationThread 是 Activitythread 的内部类,就是通过 AIDL 创建的一个远程服务的接口,用来与服务端进行交互,该对象会被传入到 AMS 中,在 AMS 中回保存他的 client(客户端),这样 AMS 就可以与应用进程进行通信了
3. IBinder token:Binder 对象,指向了服务端一个 ActivityRecord 对象
4. Activity target:当前的 Activity
5. Intent intent, int requestCode, Bundle options :Intent 对象,请求码和参数。

下面我们来看一下 execStartActivity 方法:

public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
//应用端 AIDL 实现类
IApplicationThread whoThread = (IApplicationThread) contextThread;

try {
intent.migrateExtraStreamToClipData(who);
intent.prepareToLeaveProcess(who);
//通过 Binder 调用 ATMS 启动 Activity
int result = ActivityTaskManager.getService().startActivity(whoThread,
who.getOpPackageName(), who.getAttributionTag(), 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;
}

public static IActivityTaskManager getService() {
return IActivityTaskManagerSingleton.get();
}
//获取单例
@UnsupportedAppUsage(trackingBug = 129726065)
private static final Singleton IActivityTaskManagerSingleton =
new Singleton() {
@Override
protected IActivityTaskManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
return IActivityTaskManager.Stub.asInterface(b);
}
};

我们可以用一张图来表示上述的流程:

image-20221221164643149

上面代码中通过 getService 获取到 Binder 对象,然后将 Binder 转成 AIDL 接口所属的类型,接着就可以调用 AIDL 中的方法与服务端进行通信了。

接着调用 ATMS 中的 startActivity() 方法发起启动 Activity 请求,获得启动结果 result。在调用 checkStartActivityResult 方法,传入 result,来判断能否启动 Activity,不能启动就会抛出异常,例如 activity 未在 manifest 中声明等。

二 、ATMS

通过上面的代码可以看出已经调用到了系统的 ATMS 当中,我们来看一下具体的流程

#ActivityTaskManagerService.java
@Override
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());
}

#ActivityTaskManagerService.java
public int startActivityAsUser(IApplicationThread caller, String callingPackage,
String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
Bundle bOptions, int userId) {
return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
true /validateIncomingUser/);
}

#ActivityTaskManagerService.java
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) {
//检查调用者权限
userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
Binder.getCallingPid(), Binder.getCallingUid(), “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();
}

上面代码最终调用到了 startActivityAsUser 方法,在内部将所有点的参数都交给了 ActivityStarter ,该类包含了启动的所有逻辑,比如 Intent 解析以及任务栈等。

接着调用了obtainStarter ,该方法通过工厂模式创建了 ActivityStarter 对象,如下所示:

#ActivityStarter.java
static class DefaultFactory implements Factory {
/**

  • ActivitySatrter 最大数量
    */
    private final int MAX_STARTER_COUNT = 3;

    //同步池
    private SynchronizedPool mStarterPool =
    new SynchronizedPool<>(MAX_STARTER_COUNT);

DefaultFactory(ActivityTaskManagerService service,
ActivityTaskSupervisor supervisor, ActivityStartInterceptor interceptor) {
mService = service;
mSupervisor = supervisor;
mInterceptor = interceptor;
}

@Override
public void setController(ActivityStartController controller) {
mController = controller;
}

@Override
public ActivityStarter obtain() {
//从同步池中获取 ActivityStarter 对象
ActivityStarter starter = mStarterPool.acquire();
if (starter == null) {
if (mService.mRootWindowContainer == null) {
throw new IllegalStateException(“Too early to start activity.”);
}
starter = new ActivityStarter(mController, mService, mSupervisor, mInterceptor);
}
return starter;
}

@Override
public void recycle(ActivityStarter starter) {
starter.reset(true /* clearRequest*/);
mStarterPool.release(starter);
}
}

可以看到,默认的工厂在提供了一个容量为 3 的同步缓存池来缓存 ActivityStarter 对象,该对象创建完成之后,该对象创建完成之后,AMTS 就会将接下来启动 Activity 的操作交给 ActivityStarter 来完成。

#ActivityStarter.java
//根据前面传入的参数解析一下必要的信息,并开始启动 Activity
int execute() {
try {
int res;
synchronized (mService.mGlobalLock) {

res = executeRequest(mRequest);//开始执行请求

return getExternalResult(res);
}
} finally {
onExecutionComplete();
}
}

#ActivityStarter.java
private int executeRequest(Request request) {

//检测Activity启动的权限
boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,requestCode, callingPid, callingUid, callingPackage, callingFeatureId,request.ignoreTargetSecurity, inTask != null, callerApp, resultRecord, resultRootTask);
abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
callingPid, resolvedType, aInfo.applicationInfo);
abort |= !mService.getPermissionPolicyInternal().checkStartActivity(intent, callingUid,
callingPackage);

final ActivityRecord r = new ActivityRecord.Builder(mService)
.setCaller(callerApp)
.setLaunchedFromPid(callingPid)
.setLaunchedFromUid(callingUid)
.setLaunchedFromPackage(callingPackage)
.setLaunchedFromFeature(callingFeatureId)
.setIntent(intent)
.setResolvedType(resolvedType)
.setActivityInfo(aInfo)
.setConfiguration(mService.getGlobalConfiguration())
.setResultTo(resultRecord)
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setComponentSpecified(request.componentSpecified)
.setRootVoiceInteraction(voiceSession != null)
.setActivityOptions(checkedOptions)
.setSourceRecord(sourceRecord)
.build();

mLastStartActivityRecord = r;

mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask,
restrictedBgActivity, intentGrants);

return mLastStartActivityResult;
}

上面代码中会进行一些校验和判断权限,包括进程检查,intent检查,权限检查等,后面就会创建 ActivityRecord ,每个 Activity 都会对应一个 ActivityRecord 对象,接着就会调用 startActivityUnchecked 方法对要启动的 Activity 做任务栈管理。

#ActivityStarter.java
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, Task inTask,
boolean restrictedBgActivity, NeededUriGrants intentGrants) {
int result = START_CANCELED;
final Task startedActivityRootTask;
try {
mService.deferWindowLayout();
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, “startActivityInner”);
result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
startedActivityRootTask = handleStartResult(r, result);
mService.continueWindowLayout();
}

postStartActivityProcessing(r, result, startedActivityRootTask);

return result;
}

在大多数初步检查已经完成的情况下开始进行下一步确认拥有必要的权限。 上面的核心方法就是 startActivityInner() 用来检查启动所必须要有的权限

#ActivityStarter.java
int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, Task inTask,
boolean restrictedBgActivity, NeededUriGrants intentGrants) {
//设置初始化状态
setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
voiceInteractor, restrictedBgActivity);
//判断启动模式,并且在 mLaunchFlags 上追加对应标记
computeLaunchingTaskFlags();
//设置 Activity 的栈
computeSourceRootTask();
//设置 LaunchFlags 到 intent 上
mIntent.setFlags(mLaunchFlags);

//决定是否应将新活动插入现有任务中。返回null, 如果不是则应将新活动添加到其中的任务进行活动记录
final Task reusedTask = getReusableTask();

//reusedTask 为 null 则计算是否存在可以使用的任务栈
final Task targetTask = reusedTask != null ? reusedTask : computeTargetTask();
//是否需要创建栈
final boolean newTask = targetTask == null;
mTargetTask = targetTask;

computeLaunchParams(r, sourceRecord, targetTask);

//检查是否允许在给定任务或新任务上启动活动
int startResult = isAllowedToStart(r, newTask, targetTask);
if (startResult != START_SUCCESS) {
return startResult;
}

final ActivityRecord targetTaskTop = newTask
? null : targetTask.getTopNonFinishingActivity();
if (targetTaskTop != null) {
// Recycle the target task for this launch.
startResult = recycleTask(targetTask, targetTaskTop, reusedTask, intentGrants);
if (startResult != START_SUCCESS) {
return startResult;
}
} else {
mAddingToTask = true;
}

//如果正在启动的活动与当前位于顶部的活动相同
//则需要检查它是否应该只启动一次
final Task topRootTask = mPreferredTaskDisplayArea.getFocusedRootTask();
if (topRootTask != null) {
startResult = deliverToCurrentTopIfNeeded(topRootTask, intentGrants);
if (startResult != START_SUCCESS) {
return startResult;
}
}

//复用或者创建新栈
if (mTargetRootTask == null) {
mTargetRootTask = getLaunchRootTask(mStartActivity, mLaunchFlags, targetTask, mOptions);
}
if (newTask) {
//新建一个 Task
final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
? mSourceRecord.getTask() : null;
setNewTask(taskToAffiliate);
} else if (mAddingToTask) {
//复用之前的 Task
addOrReparentStartingActivity(targetTask, “adding to task”);
}


if (mDoResume) {
// 调用 resumeFocusedTasksTopActivities方法
mRootWindowContainer.resumeFocusedTasksTopActivities(
mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);
}
mRootWindowContainer.updateUserRootTask(mStartActivity.mUserId, mTargetRootTask);

return START_SUCCESS;
}

在上面方法中,根据启动模式计算出 flag,然后在根据 flag 等条件判断要启动的 Activity 的 ActivityRecord 是需要新创建 Task 栈 还是加入到现有的 Task 栈。

在为 Activity 准备好 Task 栈之后,调用了 mRootWindowContainer.resumeFocuredTasksTopActivities 方法。

#RootWindowContainer.java
boolean resumeFocusedTasksTopActivities(
Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions,
boolean deferPause) {
boolean result = false;
if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea()
|| getTopDisplayFocusedRootTask() == targetRootTask)) {
result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions,deferPause);
}
return result;
}

#Task.java
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options,boolean deferPause) {
if (mInResumeTopActivity) {
// Don’t even start recursing.
return false;
}

boolean someActivityResumed = false;
try {
// Protect against recursion.
mInResumeTopActivity = true;

someActivityResumed = resumeTopActivityInnerLocked(prev,options,deferPause);
} finally {
mInResumeTopActivity = false;
}

return someActivityResumed;
}

#Task.java
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options,
boolean deferPause) {
if (!mAtmService.isBooting() && !mAtmService.isBooted()) {
// Not ready yet!
return false;
}

// 在当前 Task 栈中找到最上层正在运行的 Activity
// 如果这个 Activity 没有获取焦点,那这个 Activity 将会被重新启动
ActivityRecord next = topRunningActivity(true /* focusableOnly */);

if (next.attachedToProcess()) {

} else {

//调用 ActivityTaskSupervisor.startSpecificActivity
mTaskSupervisor.startSpecificActivity(next, true, true);
}

return true;
}

#ActivityTaskSupervisor.java
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
// 获取目标进程
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);

boolean knownToBeDead = false;
if (wpc != null && wpc.hasThread()) {
try {
//如果进程存在,启动 Activity 并返回
realStartActivityLocked(r, wpc, andResume, checkConfig);
return;
} catch (RemoteException e) {

}
knownToBeDead = true;
}
r.notifyUnknownVisibilityLaunchedForKeyguardTransition();
final boolean isTop = andResume && r.isTopRunningActivity();
// 进程不存在,则创建进程,并启动 Activity
mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? “top-activity” : “activity”);
}

如果进程不存在,则会创建进程,如果进程存在,则执行此方法

boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
boolean andResume, boolean checkConfig) throws RemoteException {

// 创建启动 Activity 的事务
// proc.getThread() 获取的是一个 IApplicationThread 对象
final ClientTransaction clientTransaction = ClientTransaction.obtain(
proc.getThread(), r.appToken);

final boolean isTransitionForward = r.isTransitionForward();
// 为事务设置 Callback LaunchActivityItem,在客户端时会被调用
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent), System.identityHashCode®, r.info,
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
r.getSavedState(), r.getPersistentSavedState(), results, newIntents,
r.takeOptions(), isTransitionForward,
proc.createProfilerInfoIfNeeded(), r.assistToken,
activityClientController,
r.createFixedRotationAdjustmentsIfNeeded(), r.shareableActivityToken,
r.getLaunchedFromBubble()));

最后

**一个零基础的新人,我认为坚持是最最重要的。**我的很多朋友都找我来学习过,我也很用心的教他们,可是不到一个月就坚持不下来了。我认为他们坚持不下来有两点主要原因:

他们打算入行不是因为兴趣,而是因为所谓的IT行业工资高,或者说完全对未来没有任何规划。

刚开始学的时候确实很枯燥,这确实对你是个考验,所以说坚持下来也很不容易,但是如果你有兴趣就不会认为这是累,不会认为这很枯燥,总之还是贵在坚持。

技术提升遇到瓶颈了?缺高级Android进阶视频学习提升自己吗?还有大量大厂面试题为你面试做准备!

提升自己去挑战一下BAT面试难关吧

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

对于很多Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。整理的这些知识图谱希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

不论遇到什么困难,都不应该成为我们放弃的理由!

如果有什么疑问的可以直接私我,我尽自己最大力量帮助你!

最后祝各位新人都能坚持下来,学有所成。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

易,但是如果你有兴趣就不会认为这是累,不会认为这很枯燥,总之还是贵在坚持。

技术提升遇到瓶颈了?缺高级Android进阶视频学习提升自己吗?还有大量大厂面试题为你面试做准备!

提升自己去挑战一下BAT面试难关吧

[外链图片转存中…(img-uwNwrN7r-1713618716017)]

对于很多Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。整理的这些知识图谱希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

不论遇到什么困难,都不应该成为我们放弃的理由!

如果有什么疑问的可以直接私我,我尽自己最大力量帮助你!

最后祝各位新人都能坚持下来,学有所成。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-I5Afm1Mc-1713618716017)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值