Activity的启动流程学习记录
学习章节为:《Android开发艺术探索》第9章+《Android源码设计模式解析与实战》第5、15章
前言
看了刚哥的艺术探索和源码设计模式感觉一脸懵逼,于是尝试着自己看源码,发现更加懵逼了。。。先不说逻辑,就是里面的各种属性、对象、方法之类的都看的眼花缭乱,甚至有点反胃。。。不过俗话说的好书读百遍其义自见,在不断的尝试和思考后,终于算是有了一点点懂了。所以记下来,作为记录,也作为后续深入的基础。
一般来说,我们程序员通常喜欢把很复查的操作一层一层封装起来,使得最后暴露出来的接口很简单,让使用者无脑使用而不需要关注底层的实现。而Android系统做的也是这种事儿。我们使用一个Activity只需要建立、注册、调用onCreate()开始操作即可,而底层的东西Android工程师们都帮我们写好了。而写好的那部分,也是一层一层的封装。我们读源码的时候就是需要逆序而行,把这一层一层的封装给拆开来。当然过程肯定也是从外向内, 从表层到底层的。
底层的东西以我的水平看不大清楚,所以本文所述记录还是会非常多的停留在表层。静待后续探索。(如果想看还行的,直接跳到最后,看最后一个链接就行了。)
开始~
主要涉及的类有
Activity
、ActivityThread
及其内部类ApplicationThread
、ActivityManagerService
、ActivityStackSupervisor
等。其实里头还有好多类,但是跟Activity
启动相关的,先关注这几个类。
- 首先让我们回想一下我们启动一个Activity是如何启动的:
就是通过使用
startActivity(new Intent(MainActivity.this,xxxActivity.class))
来启动一个Activity。而这个方法最后会调用 startActivityForResult()
方法,如下:
//Activity.java中
public void startActivityForResult(@RequiresPermission 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());
}
...
}
上面的 mInstrumentation.execStartActivity()
如下:
//Instrumentation.java中
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
...
/**
*上面execStartActity()中传入的参数需要所以说。
*Context 输入了 this
*IBinder 传入了 mMainThread.getApplicationThread() ____这个ApplicationThread不得了,很重要。
Intent 传入了咱们的 new Intent(MainActivity.this,xxxActivity.class)
*/
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = ActivityManager.getService() 这儿,看这里
.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) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
要注意代码中说的传入参数哦,很重要。然后看 ActivityManager.getService().startActivity()
这个方法,我的 AOSP
中直接使用 ctrl + B
是看不到 startActivity()
这个方法的,所以只有先看一下 getService()
是个何方神圣:
//ActivityManager.java中
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
private static final Singleton IActivityManagerSingleton =
new Singleton() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);这儿,熟不熟悉哈哈
return am;
}
};
所以其实,是个Binder()机制的用法。在 AIDL
的用法中我们直到服务端是会有一个类来实现 .Stub
然后做具体的事情了。根据两本书的介绍,这个类就是大名鼎鼎的 ActivityManagerService
。所以这里记住了所有调用 ActivityManager.getService().xxxx
的操作都可以直接到 AMS
中找实现方法。所以我们直接到 AMS
中找 startActivity()
方法如下:
//ActivityManagerService.java中
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, ...) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
...);
}
@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, ... ,int startFlags, ...) { 这里还有个startFlags,熟不熟悉~2333
enforceNotIsolatedCaller("startActivity");
...
敲黑板,下面的方法,我的 AOSP 中是 mActivityStarter. 而 刚哥书上的是 mStackSupervisor
//不过我在AMS的构造方法中发现了这个:
//mActivityStarter = new ActivityStarter(this, mStackSupervisor);
//所以其实ActivityStarter可能还是调用了ActivityStackSupervisor。
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, bOptions, false, userId, null, "startActivityAsUser");
}
上面方法的传入参数我省略了很多,在这里可以看到之前说的很重要的 ApplicationThread
和 Intent
一起全程跟了下来。然后就进入。。。卧槽,太复杂了(其实是我没找到那条调用链))。。。我们就直接说最后的结果吧
最后经过 ActivityStackSupervisor -> ActivityStack -> ActivityStackSupervisor
我们最终找到了如下代码:
//ActivityStackSupervisor.java 中
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);
...
if (app != null && app.thread != null) {
try {
...
realStartActivityLocked(r, app, andResume, checkConfig); 这儿,看这里
return;
} catch (RemoteException e) {
...
}
...
}
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
----------------------下面是realStartActivityLocked----------------------
省略了N多代码。
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), 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);
...
return true;
}
这个 app.thread
很重要。还记得之前在代码中说的
IBinder 传入了 mMainThread.getApplicationThread() ____这个ApplicationThread不得了,很重要。
么,app.thread就是这样玩意儿。那这玩意儿又是啥呢?
//ActivityThread.java 中
final ApplicationThread mAppThread = new ApplicationThread();
//ActivityThread内部类 ApplicationThread
private class ApplicationThread extends IApplicationThread.Stub {
...
看到 .Stub很熟悉吧,说明这个ApplicationThread也是个Binder服务端的执行者,
类里写的是接收消息后的执行代码
}
而这个 ActivityThread
我们在学习 Handler
机制的时候知道:在其 main
入口方法开启了主线程的消息循环。
当我们新点开一个应用后,Zygote
在 fork
一个子进程后就会执行 ActivityThread
的 main
方法。
app.Thread.scheduLeLaunchActivity()
最终执行在 ActvitiyThread
的内部类 ApplicationThread
中。
插播一个小猜想:我们活动A用Intent开启别人应用的活动B,那么活动B其实是运行在活动A所在的进程中的。
但是上述猜测是错误的,因为我用demo试了。。。可是不知道该如何在源码中找到依据。字体加粗警告,上面这段话是错的
然后我们继续上面的来看看 app.thread.scheduleLaunchActivity()
真正的执行调用。如下:
//ActivityThread.java 的内部类 ApplicationThread 中
// we use token to identify this activity without having to send the
// activity itself back to the activity manager. (matters more with ipc)
@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
...) {
...
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
...
sendMessage(H.LAUNCH_ACTIVITY, r); 这儿,看这儿~ LAUNCH_ACTIVITY ~
}
上面代码中的 LAUNCH_ACTIVITY
是不是看着很振奋人心 ~ ,没错,我们最初的 startActivity(new Intent(...))
方法最后来到了我们的 ActivityThread
中。并且,创建 Activity
的工作也是在这里做的。
从之前的知道 ApplicationThread
类负责执行 Binder
发送过来的指令,所以我们继续观察这个类里头的方法,就会发现和 scheduleLaunchActivity()
非常类似的许多方法,比如:
private class ApplicationThread extends IApplicationThread.Stub {
public final void scheduleResumeActivity(IBinder token, int processState,...) {
...
sendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0, 0, seq); }
public final void scheduleNewIntent(List intents, IBinder token,...) {
...
sendMessage(H.NEW_INTENT, data); }
public final void scheduleBindService(IBinder token, Intent intent, ...) {
...
sendMessage(H.BIND_SERVICE, s); }
public void scheduleRegisteredReceiver(IIntentReceiver receiver,...) ... {
...
receiver.performReceive(intent, ...); }
...
}
嘿嘿是不是很兴奋。Activity 、Service 、BroadcastReceiver
的许多操作这儿都能找到踪影。(由于我并没有用过ContentProvider,所以不知道这儿有没有,各位可以自己看一看。)
另外我们也注意到了,很多方法下面都有个 sendMessage()
的方法。比如说我们的 sendMessage(H.LAUNCH_ACTIVITY, r);
,经常用Handler的我们应该也很熟悉了,这个就是发送消息呗。看看发的消息的最后的调用:
//ActivityThread.java中
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
...
Message msg = Message.obtain();
...
mH.sendMessage(msg);这个mH看下面
}
--------------mH----------------------
final H mH = new H(); H里面的handleMessage如下:
--------------H----------------------
private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
...
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.loadedApk = getLoadedApkNoCheck(r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case RELAUNCH_ACTIVITY:
....
这个 H
里面的各种 case
就是我们非常熟悉的东西。各位可以自己看看。我们继续来瞅瞅 handleLaunchActivity()
里做了啥:
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
...
这里,看这儿。一个Activity被创建了出来
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
Bundle oldState = r.state;
下面这个方法 ~ 最后会调用 Activity 的 onResume 方法 ~ 分析可以见后面
//所以我们的 onCreate 、 onStart 在哪儿呢,在上面的performLaunch中 ~
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
if (!r.activity.mFinished && r.startsNotResumed) {
performPauseActivityIfNeeded(r, reason);
if (r.isPreHoneycomb()) {
r.state = oldState;
}
}
} else {
// If there was an error, for any reason, tell the activity manager to stop us.
上面这个官方注释:如果这儿有错误,不管是什么原因,告诉ActivityManagerService来停止我们。
所以我们至少知道了,如果要停止Activity需要由自己告诉AMS来停止自己。
try {
ActivityManager.getService().finishActivity(r.token,...);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}
接着看 performLaunchActivity()
如下:
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
重点之一!我们的Context在这儿创建
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
重点之二!类加载器加载一个类然后创建
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
...
}
try {
重点之三!创建Application(当然这里面是有判断的,如果已经存在Application就不会再创建)
Application app = r.loadedApk.makeApplication(false, mInstrumentation);
-----判断的代码如下----
if (mApplication != null) {
return mApplication;
}
-----如上-------------
...
if (activity != null) {
...
appContext.setOuterContext(activity);
重点之四!把Activity与context、Application关联起来
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, window, r.configCallback);
...
重点之五!最终会调用我们的 onCreate 方法了~
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
if (!r.activity.mFinished) {
重点之六!最终会调用我们的 onStart 方法了~
activity.performStart();
r.stopped = false;
}
if (!r.activity.mFinished) {
...这里的代码和状态储存有关
}
if (!r.activity.mFinished) {
...
这个 onPostCreate 方法也挺有意思的。是当Activity彻底运行起来之后回调的
在 onStart 之后,在 onResume 之前。观看源码之后才发现还有这么多有趣的东西。
这些东西可不是我们平时见到的那张Activity生命周期图里可以看到的
mInstrumentation.callActivityOnPostCreate(activity, r.state,
r.persistentState);
...
}
}
...
上面的一系列代码都是mInstrumentation.callActivityxxxxxxx,
不过在方法里都会调用actvity.xxxxx()。
就是 :先过去,再回来。
throw new RuntimeException(
"Unable to start activity " + component
+ ": " + e.toString(), e);
...
}
return activity;
}
所以我们知道这个 performLaunchActivity
做了非常多而且非常重要的工作。致敬。
但是这一步我们还看不到界面,因为在 onResume
中才会
将
DecorView
添加到WindowManger
中,最后将Activity
的DecorView
设置为可见,并且通知AMS
渲染视图,所以在onResume
函数之后,Activity
就显示在屏幕上了。
所以后面这一块我们先放着,可以在讲解 WindowManager、Decorview
这些的时候再讲。
这时候我们返回去看。我们一开始讲解的入口是从 startActivity()
开始的,简单总结如下:
我们的
Activity
调用startActivity
发消息给AMS
,
然后AMS
操作了一波ActivityStack
和ActivityStackSupervisor
后, 发消息给ActivityThread
的内部类ApplicationThread
,
然后ApplicationThread
用Handler
发消息并在handlerMessage()
中执行Activity
的创建工作
该工作里包括了 context、application等的创建,当然application如果存在了就不会再创建,而且一般情况下其实application早就被创建了,然后和Activity绑定。
然后将DecorView
放到WindowManager
中并通知AMS
渲染视图,然后我们的Activity
就可以看到啦。
也就是说我们这套流程的讲解,前提是我们的应用已经启动了。那么我们的应用还没启动的时候是怎么个情况呢?
接下来请看:
--------------------点击APP图标打开一个新应用的流程--------------------------
自己去找跳转的感觉简直恐怖啊。。。这么纷繁的字母组成了如此复杂的系统。。。所以只好跟着别人的文章来走了。。。如下:
https://blog.csdn.net/itachi85/article/details/64123035
https://blog.csdn.net/itachi85/article/details/55047104
https://blog.csdn.net/freekiteyu/article/details/79318031
//大概直接看最后一个博客就可以了。。。。
看应用启动的源码快疯了。。。