2024年安卓最新源码解析StartActivity的过程(1),2024年最新面试高分答题示范

总结

最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的Android开发中高级必知必会核心笔记,共计2968页PDF、58w字,囊括Android开发648个知识点,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

2021年虽然路途坎坷,都在说Android要没落,但是,不要慌,做自己的计划,学自己的习,竞争无处不在,每个行业都是如此。相信自己,没有做不到的,只有想不到的。

虽然面试失败了,但我也不会放弃入职字节跳动的决心的!建议大家面试之前都要有充分的准备,顺顺利利的拿到自己心仪的offer。

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

需要这份系统化学习资料的朋友,可以戳这里获取

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

  1. startActivityForResult(intent, -1);

  2. }

  3. }

  4. public void startActivityForResult(Intent intent, int requestCode) {

  5. startActivityForResult(intent, requestCode, null);

  6. }

说明:显然,从上往下,最终都是由startActivityForResult来实现的

接着看

code:Activity#startActivityForResult

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

  1. public void startActivityForResult(Intent intent, int requestCode, Bundle options) {

  2. //一般的Activity其mParent为null,mParent常用在ActivityGroup中,ActivityGroup已废弃

  3. if (mParent == null) {

  4. //这里会启动新的Activity,核心功能都在mMainThread.getApplicationThread()中完成

  5. Instrumentation.ActivityResult ar =

  6. mInstrumentation.execStartActivity(

  7. this, mMainThread.getApplicationThread(), mToken, this,

  8. intent, requestCode, options);

  9. if (ar != null) {

  10. //发送结果,即onActivityResult会被调用

  11. mMainThread.sendActivityResult(

  12. mToken, mEmbeddedID, requestCode, ar.getResultCode(),

  13. ar.getResultData());

  14. }

  15. if (requestCode >= 0) {

  16. // If this start is requesting a result, we can avoid making

  17. // the activity visible until the result is received.  Setting

  18. // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the

  19. // activity hidden during this time, to avoid flickering.

  20. // This can only be done when a result is requested because

  21. // that guarantees we will get information back when the

  22. // activity is finished, no matter what happens to it.

  23. mStartedActivity = true;

  24. }

  25. final View decor = mWindow != null ? mWindow.peekDecorView() : null;

  26. if (decor != null) {

  27. decor.cancelPendingInputEvents();

  28. }

  29. // TODO Consider clearing/flushing other event sources and events for child windows.

  30. } else {

  31. //在ActivityGroup内部的Activity调用startActivity的时候会走到这里,内部处理逻辑和上面是类似的

  32. if (options != null) {

  33. mParent.startActivityFromChild(this, intent, requestCode, options);

  34. } else {

  35. // Note we want to go through this method for compatibility with

  36. // existing applications that may have overridden it.

  37. mParent.startActivityFromChild(this, intent, requestCode);

  38. }

  39. }

  40. }

说明:上述代码关键点都有注释了,可以发现,真正打开activity的实现在Instrumentation的execStartActivity方法中,去看看

code:Instrumentation#execStartActivity

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

  1. public ActivityResult execStartActivity(

  2. Context who, IBinder contextThread, IBinder token, Activity target,

  3. Intent intent, int requestCode, Bundle options) {

  4. //核心功能在这个whoThread中完成,其内部scheduleLaunchActivity方法用于完成activity的打开

  5. IApplicationThread whoThread = (IApplicationThread) contextThread;

  6. if (mActivityMonitors != null) {

  7. synchronized (mSync) {

  8. //先查找一遍看是否存在这个activity

  9. final int N = mActivityMonitors.size();

  10. for (int i=0; i<N; i++) {

  11. final ActivityMonitor am = mActivityMonitors.get(i);

  12. if (am.match(who, null, intent)) {

  13. //如果找到了就跳出循环

  14. am.mHits++;

  15. //如果目标activity无法打开,直接return

  16. if (am.isBlocking()) {

  17. return requestCode >= 0 ? am.getResult() : null;

  18. }

  19. break;

  20. }

  21. }

  22. }

  23. }

  24. try {

  25. intent.migrateExtraStreamToClipData();

  26. intent.prepareToLeaveProcess();

  27. //这里才是真正打开activity的地方,核心功能在whoThread中完成。

  28. int result = ActivityManagerNative.getDefault()

  29. .startActivity(whoThread, who.getBasePackageName(), intent,

  30. intent.resolveTypeIfNeeded(who.getContentResolver()),

  31. token, target != null ? target.mEmbeddedID : null,

  32. requestCode, 0, null, null, options);

  33. //这个方法是专门抛异常的,它会对结果进行检查,如果无法打开activity,

  34. //则抛出诸如ActivityNotFoundException类似的各种异常

  35. checkStartActivityResult(result, intent);

  36. } catch (RemoteException e) {

  37. }

  38. return null;

  39. }

说明:我想再说一下这个方法checkStartActivityResult,它也专业抛异常的,看代码,相信大家对下面的异常信息不陌生吧,就是它干的,其中最熟悉的非Unable to find explicit activity class莫属了,如果你在xml中没有注册目标activity,此异常将会抛出。

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

  1. /*package*/ static void checkStartActivityResult(int res, Object intent) {

  2. if (res >= ActivityManager.START_SUCCESS) {

  3. return;

  4. }

  5. switch (res) {

  6. case ActivityManager.START_INTENT_NOT_RESOLVED:

  7. case ActivityManager.START_CLASS_NOT_FOUND:

  8. if (intent instanceof Intent && ((Intent)intent).getComponent() != null)

  9. throw new ActivityNotFoundException(

  10. "Unable to find explicit activity class "

  11. + ((Intent)intent).getComponent().toShortString()

  12. + “; have you declared this activity in your AndroidManifest.xml?”);

  13. throw new ActivityNotFoundException(

  14. "No Activity found to handle " + intent);

  15. case ActivityManager.START_PERMISSION_DENIED:

  16. throw new SecurityException("Not allowed to start activity "

  17. + intent);

  18. case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:

  19. throw new AndroidRuntimeException(

  20. “FORWARD_RESULT_FLAG used while also requesting a result”);

  21. case ActivityManager.START_NOT_ACTIVITY:

  22. throw new IllegalArgumentException(

  23. “PendingIntent is not an activity”);

  24. default:

  25. throw new AndroidRuntimeException("Unknown error code "

  26. + res + " when starting " + intent);

  27. }

  28. }

接下来我们要去看看IApplicationThread,因为核心功能由其内部的scheduleLaunchActivity方法来完成,由于IApplicationThread是个接口,所以,我们需要找到它的实现类,我已经帮大家找到了,它就是ActivityThread中的内部类ApplicationThread,看下它的继承关系:

private class ApplicationThread extends ApplicationThreadNative;

public abstract class ApplicationThreadNative extends Binder implements IApplicationThread;

可以发现,ApplicationThread还是间接实现了IApplicationThread接口,先看下这个类的结构

看完ApplicationThread的大致结构,我们应该能够猜测到,Activity的生命周期中的resume、newIntent、pause、stop等事件都是由它触发的,事实上,的确是这样的。这里,我们为了说明问题,仅仅看scheduleLaunchActivity方法

code:ApplicationThread#scheduleLaunchActivity

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

  1. public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,

  2. ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,

  3. int procState, Bundle state, List pendingResults,

  4. List pendingNewIntents, boolean notResumed, boolean isForward,

  5. String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {

  6. updateProcessState(procState, false);

  7. ActivityClientRecord r = new ActivityClientRecord();

  8. r.token = token;

  9. r.ident = ident;

  10. r.intent = intent;

  11. r.activityInfo = info;

  12. r.compatInfo = compatInfo;

  13. r.state = state;

  14. r.pendingResults = pendingResults;

  15. r.pendingIntents = pendingNewIntents;

  16. r.startsNotResumed = notResumed;

  17. r.isForward = isForward;

  18. r.profileFile = profileName;

  19. r.profileFd = profileFd;

  20. r.autoStopProfiler = autoStopProfiler;

  21. updatePendingConfiguration(curConfig);

  22. queueOrSendMessage(H.LAUNCH_ACTIVITY, r);

  23. }

说明:上述代码很好理解,构造一个activity记录,然后发送一个消息,所以,我们要看看Handler是如何处理这个消息的,现在转到这个Handler,它有个很短的名字叫做H

code:ActivityThread#H

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

  1. //这个类太长,我只帖出了我们用到的部分

  2. private class H extends Handler {

  3. public void handleMessage(Message msg) {

  4. if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));

  5. switch (msg.what) {

  6. //这里处理LAUNCH_ACTIVITY消息类型

  7. case LAUNCH_ACTIVITY: {

  8. Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, “activityStart”);

  9. ActivityClientRecord r = (ActivityClientRecord)msg.obj;

  10. r.packageInfo = getPackageInfoNoCheck(

  11. r.activityInfo.applicationInfo, r.compatInfo);

  12. //这里处理startActivity消息

  13. handleLaunchActivity(r, null);

  14. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

  15. } break;

  16. case RELAUNCH_ACTIVITY: {

  17. Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, “activityRestart”);

  18. ActivityClientRecord r = (ActivityClientRecord)msg.obj;

  19. handleRelaunchActivity®;

  20. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

  21. } break;

  22. case PAUSE_ACTIVITY:

  23. Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, “activityPause”);

  24. handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);

  25. maybeSnapshot();

  26. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

  27. break;

  28. }

  29. }

说明:看来还要看handleLaunchActivity

code:ActivityThread#handleLaunchActivity

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

  1. private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {

  2. // If we are getting ready to gc after going to the background, well

  3. // we are back active so skip it.

  4. unscheduleGcIdler();

  5. if (r.profileFd != null) {

  6. mProfiler.setProfiler(r.profileFile, r.profileFd);

  7. mProfiler.startProfiling();

  8. mProfiler.autoStopProfiler = r.autoStopProfiler;

  9. }

  10. // Make sure we are running with the most recent config.

  11. handleConfigurationChanged(null, null);

  12. if (localLOGV) Slog.v(

  13. TAG, "Handling launch of " + r);

  14. //终于到底了,大家都有点不耐烦了吧,从方法名可以看出,

  15. //performLaunchActivity真正完成了activity的调起,

  16. //同时activity会被实例化,并且onCreate会被调用

  17. Activity a = performLaunchActivity(r, customIntent);

  18. if (a != null) {

  19. r.createdConfig = new Configuration(mConfiguration);

  20. Bundle oldState = r.state;

  21. //看到没,目标activity的onResume会被调用

  22. handleResumeActivity(r.token, false, r.isForward,

  23. !r.activity.mFinished && !r.startsNotResumed);

  24. if (!r.activity.mFinished && r.startsNotResumed) {

  25. // The activity manager actually wants this one to start out

  26. // paused, because it needs to be visible but isn’t in the

  27. // foreground.  We accomplish this by going through the

  28. // normal startup (because activities expect to go through

  29. // onResume() the first time they run, before their window

  30. // is displayed), and then pausing it.  However, in this case

  31. // we do -not- need to do the full pause cycle (of freezing

  32. // and such) because the activity manager assumes it can just

  33. // retain the current state it has.

  34. try {

  35. r.activity.mCalled = false;

  36. //同时,由于新activity被调起了,原activity的onPause会被调用

  37. mInstrumentation.callActivityOnPause(r.activity);

  38. // We need to keep around the original state, in case

  39. // we need to be created again.  But we only do this

  40. // for pre-Honeycomb apps, which always save their state

  41. // when pausing, so we can not have them save their state

  42. // when restarting from a paused state.  For HC and later,

  43. // we want to (and can) let the state be saved as the normal

  44. // part of stopping the activity.

  45. if (r.isPreHoneycomb()) {

  46. r.state = oldState;

学习路线+知识梳理

花了很长时间,就为了整理这张详细的知识路线脑图。当然由于时间有限、能力也都有限,毕竟嵌入式全体系实在太庞大了,包括我那做嵌入式的同学,也不可能什么都懂,有些东西可能没覆盖到,不足之处,还希望小伙伴们一起交流补充,一起完善进步。

这次就分享到这里吧,下篇见

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

需要这份系统化学习资料的朋友,可以戳这里获取

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

et the state be saved as the normal

  1. // part of stopping the activity.

  2. if (r.isPreHoneycomb()) {

  3. r.state = oldState;

学习路线+知识梳理

花了很长时间,就为了整理这张详细的知识路线脑图。当然由于时间有限、能力也都有限,毕竟嵌入式全体系实在太庞大了,包括我那做嵌入式的同学,也不可能什么都懂,有些东西可能没覆盖到,不足之处,还希望小伙伴们一起交流补充,一起完善进步。

这次就分享到这里吧,下篇见

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

需要这份系统化学习资料的朋友,可以戳这里获取

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

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值