总结
最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的Android开发中高级必知必会核心笔记,共计2968页PDF、58w字,囊括Android开发648个知识点,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
2021年虽然路途坎坷,都在说Android要没落,但是,不要慌,做自己的计划,学自己的习,竞争无处不在,每个行业都是如此。相信自己,没有做不到的,只有想不到的。
虽然面试失败了,但我也不会放弃入职字节跳动的决心的!建议大家面试之前都要有充分的准备,顺顺利利的拿到自己心仪的offer。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
-
startActivityForResult(intent, -1);
-
}
-
}
-
public void startActivityForResult(Intent intent, int requestCode) {
-
startActivityForResult(intent, requestCode, null);
-
}
说明:显然,从上往下,最终都是由startActivityForResult来实现的
接着看
code:Activity#startActivityForResult
[java] view plain copy
-
public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
-
//一般的Activity其mParent为null,mParent常用在ActivityGroup中,ActivityGroup已废弃
-
if (mParent == null) {
-
//这里会启动新的Activity,核心功能都在mMainThread.getApplicationThread()中完成
-
Instrumentation.ActivityResult ar =
-
mInstrumentation.execStartActivity(
-
this, mMainThread.getApplicationThread(), mToken, this,
-
intent, requestCode, options);
-
if (ar != null) {
-
//发送结果,即onActivityResult会被调用
-
mMainThread.sendActivityResult(
-
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
-
ar.getResultData());
-
}
-
if (requestCode >= 0) {
-
// If this start is requesting a result, we can avoid making
-
// the activity visible until the result is received. Setting
-
// this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
-
// activity hidden during this time, to avoid flickering.
-
// This can only be done when a result is requested because
-
// that guarantees we will get information back when the
-
// activity is finished, no matter what happens to it.
-
mStartedActivity = true;
-
}
-
final View decor = mWindow != null ? mWindow.peekDecorView() : null;
-
if (decor != null) {
-
decor.cancelPendingInputEvents();
-
}
-
// TODO Consider clearing/flushing other event sources and events for child windows.
-
} else {
-
//在ActivityGroup内部的Activity调用startActivity的时候会走到这里,内部处理逻辑和上面是类似的
-
if (options != null) {
-
mParent.startActivityFromChild(this, intent, requestCode, options);
-
} else {
-
// Note we want to go through this method for compatibility with
-
// existing applications that may have overridden it.
-
mParent.startActivityFromChild(this, intent, requestCode);
-
}
-
}
-
}
说明:上述代码关键点都有注释了,可以发现,真正打开activity的实现在Instrumentation的execStartActivity方法中,去看看
code:Instrumentation#execStartActivity
[java] view plain copy
-
public ActivityResult execStartActivity(
-
Context who, IBinder contextThread, IBinder token, Activity target,
-
Intent intent, int requestCode, Bundle options) {
-
//核心功能在这个whoThread中完成,其内部scheduleLaunchActivity方法用于完成activity的打开
-
IApplicationThread whoThread = (IApplicationThread) contextThread;
-
if (mActivityMonitors != null) {
-
synchronized (mSync) {
-
//先查找一遍看是否存在这个activity
-
final int N = mActivityMonitors.size();
-
for (int i=0; i<N; i++) {
-
final ActivityMonitor am = mActivityMonitors.get(i);
-
if (am.match(who, null, intent)) {
-
//如果找到了就跳出循环
-
am.mHits++;
-
//如果目标activity无法打开,直接return
-
if (am.isBlocking()) {
-
return requestCode >= 0 ? am.getResult() : null;
-
}
-
break;
-
}
-
}
-
}
-
}
-
try {
-
intent.migrateExtraStreamToClipData();
-
intent.prepareToLeaveProcess();
-
//这里才是真正打开activity的地方,核心功能在whoThread中完成。
-
int result = ActivityManagerNative.getDefault()
-
.startActivity(whoThread, who.getBasePackageName(), intent,
-
intent.resolveTypeIfNeeded(who.getContentResolver()),
-
token, target != null ? target.mEmbeddedID : null,
-
requestCode, 0, null, null, options);
-
//这个方法是专门抛异常的,它会对结果进行检查,如果无法打开activity,
-
//则抛出诸如ActivityNotFoundException类似的各种异常
-
checkStartActivityResult(result, intent);
-
} catch (RemoteException e) {
-
}
-
return null;
-
}
说明:我想再说一下这个方法checkStartActivityResult,它也专业抛异常的,看代码,相信大家对下面的异常信息不陌生吧,就是它干的,其中最熟悉的非Unable to find explicit activity class莫属了,如果你在xml中没有注册目标activity,此异常将会抛出。
[java] view plain copy
-
/*package*/ static void checkStartActivityResult(int res, Object intent) {
-
if (res >= ActivityManager.START_SUCCESS) {
-
return;
-
}
-
switch (res) {
-
case ActivityManager.START_INTENT_NOT_RESOLVED:
-
case ActivityManager.START_CLASS_NOT_FOUND:
-
if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
-
throw new ActivityNotFoundException(
-
"Unable to find explicit activity class "
-
+ ((Intent)intent).getComponent().toShortString()
-
+ “; have you declared this activity in your AndroidManifest.xml?”);
-
throw new ActivityNotFoundException(
-
"No Activity found to handle " + intent);
-
case ActivityManager.START_PERMISSION_DENIED:
-
throw new SecurityException("Not allowed to start activity "
-
+ intent);
-
case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
-
throw new AndroidRuntimeException(
-
“FORWARD_RESULT_FLAG used while also requesting a result”);
-
case ActivityManager.START_NOT_ACTIVITY:
-
throw new IllegalArgumentException(
-
“PendingIntent is not an activity”);
-
default:
-
throw new AndroidRuntimeException("Unknown error code "
-
+ res + " when starting " + intent);
-
}
-
}
接下来我们要去看看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
-
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
-
ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
-
int procState, Bundle state, List pendingResults,
-
List pendingNewIntents, boolean notResumed, boolean isForward,
-
String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
-
updateProcessState(procState, false);
-
ActivityClientRecord r = new ActivityClientRecord();
-
r.token = token;
-
r.ident = ident;
-
r.intent = intent;
-
r.activityInfo = info;
-
r.compatInfo = compatInfo;
-
r.state = state;
-
r.pendingResults = pendingResults;
-
r.pendingIntents = pendingNewIntents;
-
r.startsNotResumed = notResumed;
-
r.isForward = isForward;
-
r.profileFile = profileName;
-
r.profileFd = profileFd;
-
r.autoStopProfiler = autoStopProfiler;
-
updatePendingConfiguration(curConfig);
-
queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
-
}
说明:上述代码很好理解,构造一个activity记录,然后发送一个消息,所以,我们要看看Handler是如何处理这个消息的,现在转到这个Handler,它有个很短的名字叫做H
code:ActivityThread#H
[java] view plain copy
-
//这个类太长,我只帖出了我们用到的部分
-
private class H extends Handler {
-
public void handleMessage(Message msg) {
-
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
-
switch (msg.what) {
-
//这里处理LAUNCH_ACTIVITY消息类型
-
case LAUNCH_ACTIVITY: {
-
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, “activityStart”);
-
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
-
r.packageInfo = getPackageInfoNoCheck(
-
r.activityInfo.applicationInfo, r.compatInfo);
-
//这里处理startActivity消息
-
handleLaunchActivity(r, null);
-
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
-
} break;
-
case RELAUNCH_ACTIVITY: {
-
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, “activityRestart”);
-
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
-
handleRelaunchActivity®;
-
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
-
} break;
-
case PAUSE_ACTIVITY:
-
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, “activityPause”);
-
handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
-
maybeSnapshot();
-
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
-
break;
-
…
-
}
-
}
说明:看来还要看handleLaunchActivity
code:ActivityThread#handleLaunchActivity
[java] view plain copy
-
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
-
// If we are getting ready to gc after going to the background, well
-
// we are back active so skip it.
-
unscheduleGcIdler();
-
if (r.profileFd != null) {
-
mProfiler.setProfiler(r.profileFile, r.profileFd);
-
mProfiler.startProfiling();
-
mProfiler.autoStopProfiler = r.autoStopProfiler;
-
}
-
// Make sure we are running with the most recent config.
-
handleConfigurationChanged(null, null);
-
if (localLOGV) Slog.v(
-
TAG, "Handling launch of " + r);
-
//终于到底了,大家都有点不耐烦了吧,从方法名可以看出,
-
//performLaunchActivity真正完成了activity的调起,
-
//同时activity会被实例化,并且onCreate会被调用
-
Activity a = performLaunchActivity(r, customIntent);
-
if (a != null) {
-
r.createdConfig = new Configuration(mConfiguration);
-
Bundle oldState = r.state;
-
//看到没,目标activity的onResume会被调用
-
handleResumeActivity(r.token, false, r.isForward,
-
!r.activity.mFinished && !r.startsNotResumed);
-
if (!r.activity.mFinished && r.startsNotResumed) {
-
// The activity manager actually wants this one to start out
-
// paused, because it needs to be visible but isn’t in the
-
// foreground. We accomplish this by going through the
-
// normal startup (because activities expect to go through
-
// onResume() the first time they run, before their window
-
// is displayed), and then pausing it. However, in this case
-
// we do -not- need to do the full pause cycle (of freezing
-
// and such) because the activity manager assumes it can just
-
// retain the current state it has.
-
try {
-
r.activity.mCalled = false;
-
//同时,由于新activity被调起了,原activity的onPause会被调用
-
mInstrumentation.callActivityOnPause(r.activity);
-
// We need to keep around the original state, in case
-
// we need to be created again. But we only do this
-
// for pre-Honeycomb apps, which always save their state
-
// when pausing, so we can not have them save their state
-
// when restarting from a paused state. For HC and later,
-
// we want to (and can) let the state be saved as the normal
-
// part of stopping the activity.
-
if (r.isPreHoneycomb()) {
-
r.state = oldState;
学习路线+知识梳理
花了很长时间,就为了整理这张详细的知识路线脑图。当然由于时间有限、能力也都有限,毕竟嵌入式全体系实在太庞大了,包括我那做嵌入式的同学,也不可能什么都懂,有些东西可能没覆盖到,不足之处,还希望小伙伴们一起交流补充,一起完善进步。
这次就分享到这里吧,下篇见。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
et the state be saved as the normal
-
// part of stopping the activity.
-
if (r.isPreHoneycomb()) {
-
r.state = oldState;
学习路线+知识梳理
花了很长时间,就为了整理这张详细的知识路线脑图。当然由于时间有限、能力也都有限,毕竟嵌入式全体系实在太庞大了,包括我那做嵌入式的同学,也不可能什么都懂,有些东西可能没覆盖到,不足之处,还希望小伙伴们一起交流补充,一起完善进步。
这次就分享到这里吧,下篇见。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!