App 启动过程(含 Activity 启动过程) _ 安卓 offer 收割基


mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
inTask);
}

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java#294
private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
ActivityRecord[] outActivity, TaskRecord inTask) {

return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
options, inTask, outActivity);
}

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java#988
private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {

result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, outActivity);

}

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java#1015
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {

mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);

}

6. 到 ActivityStackSupervisor#resumeFocusedStackTopActivityLocked 中查看发现其调用了 ActivityStack#resumeTopActivityUncheckedLocked,然后是 ActivityStack#resumeTopActivityInnerLocked,接着变又回到 ActivityStackSupervisor.java,调用了 ActivityStackSupervisor#startSpecificActivityLocked,这个方法中会判断要启动 App 的进程是否存在,存在则通知进程启动 Activity,否则就先将进程创建出来,其源码如下所示:

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java#2085
boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {

return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);

}

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/services/core/java/com/android/server/am/ActivityStack.java#2245
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {

result = resumeTopActivityInnerLocked(prev, options);

}

http://androidxref.com/8.1.0_r33/xref/frameworks/base/services/core/java/com/android/server/am/ActivityStack.java#2286
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {

mStackSupervisor.startSpecificActivityLocked(next, true, true);

}

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java#1560
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {

if (app != null && app.thread != null) {

// 如果进程已存在,则通知进程启动组件
realStartActivityLocked(r, app, andResume, checkConfig);
return;

}
// 否则先将进程创建出来
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
“activity”, r.intent.getComponent(), false, false, true);

}

7. 我们分析进程尚未存在的情况,因为我们后续还会再次遇到 ActivityStackSupervisor#realStartActivityLockedActivityStackSupervisor#startSpecificActivityLocked 中创建进程使用到的 mServiceActivityManagerService,我们查看 ActivityManagerService#startProcessLocked 的源码如下所示:

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java#3777
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {

if (entryPoint == null) entryPoint = “android.app.ActivityThread”;
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, entryPointArgs);

}

8. 发现最终调用的事 Process#start 来启动进程,进程的入口就是在 android.app.ActivityThread.java 类中的 main() 函数,因此接下来我们从 ActivityThread#main 来分析,其调用了 ActivityThread#attach,其中 ActivityManager.getService() 之前提到过,返回的是一个是实现 IActivityManager 类型的 Binder 对象,它的具体实现是在 ActivityManagerService 中,相关源码如下所示:

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/ActivityThread.java#6459
public static void main(String[] args) {

Looper.prepareMainLooper();

ActivityThread thread = new ActivityThread();
thread.attach(false);

Looper.loop();

}

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/ActivityThread.java#6315
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {

final IActivityManager mgr = ActivityManager.getService();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {

}

}

}

9. 我们又回到了 ActivityManagerService 中,查看其 attachApplication 函数,发现调用了 thread#bindApplicationmStackSupervisor#attachApplicationLocked 我们依次讲解这两个方法要做的事情,源码如下所示:

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java#7215
public final void attachApplication(IApplicationThread thread) {

attachApplicationLocked(thread, callingPid);

}

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java#6911
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {

thread.bindApplication(processName, appInfo, providers,
app.instr.mClass,
profilerInfo, app.instr.mArguments,
app.instr.mWatcher,
app.instr.mUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(getGlobalConfiguration()), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial);

if (normalMode) {
try {
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
} catch (Exception e) {

}
}

}

10. 上面说到的thread#bindApplication 中的这个 thread 是来自于 ActivityThread#mAppThread,其类型是 ApplicationThread,是 ActivityThread 的一个内部类,继承自 IApplicationThread.Stub,我们来查看 ApplicationThread#bindApplication,发现最后调用了 ActivityThread#sendMessage 方法,它内部调用了 mH.sendMessage 来发送消息,mHActivityThread 的内部类 H 的一个实例,查看 H#handleMessage 来查看它是怎么处理发送过来的消息,其最终走到了 ActivityThread#handleBindApplication

在源码中我们可以发现它先创建 mInstrumentation 对象,调用 data#info#makeApplication 来创建 Application 对象,其对象 data#infoLoadedApk 的一个实例,查看 LoadedApk#makeApplication 中代码可以发现,其调用了 Instrumentation#newApplication 方法,内部靠 Class#newInstance() 完成对 Application 实例化,然后调用 Application#attach(context) 来绑定 Context

以上创建完 Application 对象后便是调用 Instrumentation#callApplicationOnCreateApplicationonCreate 生命周期,以上涉及到的全部源码如下所示:

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/ActivityThread.java#899
public final void bindApplication(String processName, ApplicationInfo appInfo,
List providers, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableBinderTracking, boolean trackAllocation,
boolean isRestrictedBackupMode, boolean persistent, Configuration config,
CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
String buildSerial) {

sendMessage(H.BIND_APPLICATION, data);
}

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/ActivityThread.java#2593
private void sendMessage(int what, Object obj) {
sendMessage(what, obj, 0, 0, false);
}

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)

  • ": " + arg1 + " / " + obj);
    Message msg = Message.obtain();
    msg.what = what;
    msg.obj = obj;
    msg.arg1 = arg1;
    msg.arg2 = arg2;
    if (async) {
    msg.setAsynchronous(true);
    }
    mH.sendMessage(msg);
    }

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/ActivityThread.java#1580
public void handleMessage(Message msg) {

switch (msg.what) {

case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, “bindApplication”);
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;

}
}

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/ActivityThread.java#5429
private void handleBindApplication(AppBindData data) {

final InstrumentationInfo ii;

// 创建 mInstrumentation 实例
if (ii != null) {
final ApplicationInfo instrApp = new ApplicationInfo();
ii.copyTo(instrApp);
instrApp.initForUser(UserHandle.myUserId());
final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
appContext.getClassLoader(), false, true, false);
final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);

try {
final ClassLoader cl = instrContext.getClassLoader();
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
} catch (Exception e) {

}

} else {
mInstrumentation = new Instrumentation();
}

Application app;

// 创建 Application 实例
try {

app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;

try {
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {

}
} finally {

}

}

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/LoadedApk.java#959
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
Application app = null;

String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = “android.app.Application”;
}

try {
java.lang.ClassLoader cl = getClassLoader();

ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {

}
mActivityThread.mAllApplications.add(app);
mApplication = app;

if (instrumentation != null) {// 传入为 null 所以不走
try {
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {

}
}

return app;
}

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/Instrumentation.java#1084
public Application newApplication(ClassLoader cl, String className, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
return newApplication(cl.loadClass(className), context);
}

static public Application newApplication(Class<?> clazz, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
Application app = (Application)clazz.newInstance();
app.attach(context);
return app;
}

11. 说完了 9 中的 thread#bindApplication,下面我们继续说 mStackSupervisor#attachApplicationLocked,其 mStackSupervisorActivityStackSupervisor 的一个实例,我们查看 ActivityStackSupervisor#attachApplicationLocked 方法中发现会调用 ActivityStackSupervisor#realStartActivityLocked,其方法会调用 app#thread#scheduleLaunchActivity,源码如下所示:

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java#956
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
final String processName = app.processName;

if (realStartActivityLocked(activity, app,
top == activity /* andResume /, true / checkConfig */)) {

}

}

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java#1313
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {

app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode®, r.info,
// TODO: Have this take the merged configuration instead of separate global
// and override configs.
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
r.persistentState, results, newIntents, !andResume,
mService.isNextTransitionForward(), profilerInfo);

}

12. 上面说到的 app#thread#scheduleLaunchActivity 中的 thread 是前面提到过的 IApplicationThread,它的实现类是 ActivityThread#ApplicationThread ,我们查看 ActivityThread#ApplicationThread#scheduleLaunchActivity 中的代码发现最终是发送 LAUNCH_ACTIVITY 消息,这步我们在第 10 步中有过分析,我们直接查看其处理消息相关代码即可,在 H#handleMessage 中,我们可以看到其会接收并处理很多和四大组件相关的操作,我们查看对 LAUNCH_ACTIVITY 的处理,发现对其处理的方法是 ActivityThread#handleLaunchActivity,它调用到了 ActivityThread#performLaunchActivity 方法,其中的实现再次涉及到了 Instrumentation 类,之前是在创建 Application 对象用到了它,如今是创建 Activity 对象又用到了它,其 Instrumentation#newActivity 也是通过 Class.newInstance() 来实例化 Activity,实例化结束后回到 ActivityThread#performLaunchActivity 中来让 activity 依附到 window 中,然后callActivityOnCreateActivityonCreate 生命周期,涉及到的源码如下所示:

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/ActivityThread.java#756
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
int procState, Bundle state, PersistableBundle persistentState,
List pendingResults, List pendingNewIntents,
boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

sendMessage(H.LAUNCH_ACTIVITY, r);
}

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/ActivityThread.java#1580
public void handleMessage(Message msg) {

switch (msg.what) {

case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, “activityStart”);
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, “LAUNCH_ACTIVITY”);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;

}
}

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/ActivityThread.java#2833
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {

Activity a = performLaunchActivity(r, customIntent);

}

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/ActivityThread.java#2644
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);

} catch (Exception e) {

}

try {
// 返回之前创建过的 application 对象
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

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

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

文末

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

最后想要拿高薪实现技术提升薪水得到质的飞跃。最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。

当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。

进阶学习视频

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。

当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。

进阶学习视频

[外链图片转存中…(img-waPY72J7-1712250647125)]

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

[外链图片转存中…(img-GxBHk302-1712250647126)]

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值