Android:图解Activity启动流程源码(整体流程)
Posted 鸽一门
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android:图解Activity启动流程源码(整体流程)相关的知识,希望对你有一定的参考价值。
Intent intent = new Intent(this, TestActivity.class);
startActivity(intent);
以上代码对于android开发者再熟悉不过了,功能即启动 TextActivity。这是最基本的Intent使用知识,通过显示Intent来触发 Activity的启动,而Activity,四大组件中的老大,是一种展示型组件,用于向用户展示交互界面,如此重要的一个角色,类似于以上的代码,每天都在写,可是有几个问题是否想过:
- 系统内部是如何启动一个Activity?
- 当启动一个新Activity时,该对象是在何时创建的?
- Application 的onCreate方法又是在何时被系统回调?
- Activity 的onCreate方法又是在何时被系统回调?
接下来从源码的角度来分析解决以上问题,注意:由于Android内部实现比较复杂,所以以下分析更侧重于整体流程,对Activity启动建立一个整体的意识。
一. Activity启动流程步骤
Step 1. 启动Activity
Intent intent = new Intent(this, TestActivity.class);
startActivity(intent);
Step 2. Activity的startActivityForResult 方法
Activity的启动调用的就是startActivity方法,此方法有多种重载方式,但最后都会调用 startActivityForResult 方法,实现如下:
【Activity 类】
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());
if (requestCode >= 0)
//
mStartedActivity = true;
......
else
......
以上代码中第一行 if判断 mParent == null
即可,mParent 代表的是ActivityGroup,它最开始用来在一个界面中嵌入多个子Activity,而在API13中已经被抛弃了,因为Fragment的出现和它的高效,已经代替了ActivityGroup。
其中还要注意if判断语句中的一个参数 mMainThread.getApplicationThread()
,它的类型为 ApplicationThread,而ApplicationThread 是 ActivityThread的一个内部类。(通过后面分析可知,这两个类在Activity的启动过程中起重要作用)
Step 3. Instrumentation的execStartActivity方法
介绍两个基本点后,接下来查看Instrumentation 的 execStartActivity 方法。
【Instrumentation 类】
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options)
IApplicationThread whoThread = (IApplicationThread) contextThread;
Uri referrer = target != null ? target.onProvideReferrer() : null;
if (referrer != null)
intent.putExtra(Intent.EXTRA_REFERRER, referrer);
if (mActivityMonitors != null)
......
try
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
//☆☆☆☆☆ 重点!!!!!
int result = ActivityManagerNative.getDefault()
.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;
以上代码可得,启动Activity真正的实现由 ActivityManagerNative.getDefault()
的 startActivity 方法来完成,往下深入之前,先介绍一下此类相关知识:ActivityManagerService(简称AMS)继承自ActivityManagerNative,而ActivityManagerNative继承自Binder并实现了IActivityManager的具体实现。
接下来查看ActivityManagerNative的getDefault() 方法:
【ActivityManagerNative 类】
static public IActivityManager getDefault()
return gDefault.get();
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>()
protected IActivityManager create()
IBinder b = ServiceManager.getService("activity");
if (false)
Log.v("ActivityManager", "default service binder = " + b);
IActivityManager am = asInterface(b);
if (false)
Log.v("ActivityManager", "default service = " + am);
return am;
;
以上代码可知: 而 ActivityManagerNative.getDefault()
其实是一个IActivityManager类型的Binder对象,因此它的具体实现是ActivityManagerService类!而且在ActivityManagerNative类实现中,AMS此Binder对象采用Singleton单例模式对外提供。
Step 4. ActivityManagerService的startActivity方法
根据以上分析后,由原来Activity是 ActivityManagerNative.getDefault()
来启动,转移到了AMS!继续深入,直接查看AMS的startActivity方法:
【ActivityManagerService类】
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags,
String profileFile, ParcelFileDescriptor profileFd, Bundle options)
//☆☆☆☆☆ 重点!!!!!
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode,
startFlags, profileFile, profileFd, options, UserHandle.getCallingUserId());
@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags,
String profileFile, ParcelFileDescriptor profileFd, Bundle options, int userId)
.....
//☆☆☆☆☆ 重点!!!!!
return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
null, null, options, userId);
可以看出Activity的启动过程又转移到了 ActivityStackSupervisor的 startActivityMayWait方法中。但是继续往下深入之前先暂停一会,以上步骤用时序图画出来理清一下思路:
Step 5. ActivityStackSupervisor 和 ActivityStack 之间互相调用
当Activity的启动过程又转移到了 ActivityStackSupervisor后,此类不断调用自身方法并且与 ActivityStack 之间的方法回调。但是,这涉及到的方法略多,而这篇博文作为认识整体流程,就不贴相关代码了,重点不同,将两个类之间的方法回调以流程图展示,更清晰,下面会直接讲解重点方法:
以上流程图是ActivityStackSupervisor 和 ActivityStack 之间的互相调用,了解基本流程即可,这里直接看此过程的最后一个调用方法:realStartActivityLocked
【ActivityStackSupervisor 类】
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,
new Configuration(mService.mConfiguration), r.compat,
app.repProcState, r.icicle, results, newIntents, !andResume,
mService.isNextTransitionForward(), profileFile, profileFd,
profileAutoStop);
......
以上这行代码很重要,正式转移了Activity启动过程,其中需要详细介绍app.thread,它的类型就是IApplicationThread。
Step 6. ApplicationThreadNative内部类 ApplicationThreadProxy
IApplicationThread源码实现如下:
【IApplicationThread 类】
public interface IApplicationThread extends IInterface
void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving,
int configChanges) throws RemoteException;
void scheduleStopActivity(IBinder token, boolean showWindow,
int configChanges) throws RemoteException;
void scheduleWindowVisibility(IBinder token, boolean showWindow) throws RemoteException;
void scheduleSleeping(IBinder token, boolean sleeping) throws RemoteException;
void scheduleResumeActivity(IBinder token, int procState, boolean isForward)
throws RemoteException;
void scheduleSendResult(IBinder token, List<ResultInfo> results) throws RemoteException;
void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
int procState, Bundle state, List<ResultInfo> pendingResults,
List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler)
throws RemoteException;
void scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults,
List<Intent> pendingNewIntents, int configChanges,
boolean notResumed, Configuration config) throws RemoteException;
void scheduleNewIntent(List<Intent> intent, IBinder token) throws RemoteException;
void scheduleDestroyActivity(IBinder token, boolean finished,
int configChanges) throws RemoteException;
void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo,
int resultCode, String data, Bundle extras, boolean sync,
int sendingUser, int processState) throws RemoteException;
static final int BACKUP_MODE_INCREMENTAL = 0;
static final int BACKUP_MODE_FULL = 1;
static final int BACKUP_MODE_RESTORE = 2;
static final int BACKUP_MODE_RESTORE_FULL = 3;
void scheduleCreateBackupAgent(ApplicationInfo app, CompatibilityInfo compatInfo,
int backupMode) throws RemoteException;
void scheduleDestroyBackupAgent(ApplicationInfo app, CompatibilityInfo compatInfo)
throws RemoteException;
void scheduleCreateService(IBinder token, ServiceInfo info,
CompatibilityInfo compatInfo, int processState) throws RemoteException;
void scheduleBindService(IBinder token,
Intent intent, boolean rebind, int processState) throws RemoteException;
void scheduleUnbindService(IBinder token,
Intent intent) throws RemoteException;
void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,
int flags, Intent args) throws RemoteException;
void scheduleStopService(IBinder token) throws RemoteException;
......
因为IApplicationThread 类继承了 IInterface接口,所以它是一个Binder类型的接口。从IApplicationThread 声明的接口可以看出,其内部包含了大量启动、停止Activity的接口,此外还包含了启动和停止服务的接口,IApplicationThread 这个 Binder接口实现者完成了大量和Activity、Service启动/停止有关的功能。
可是IApplicationThread 的实现者到底是什么?
答案就是 ActivityThread 中的内部类 ApplicationThread。来查看一下ApplicationThread的定义:
private class ApplicationThread extends ApplicationThreadNative
.....
public abstract class ApplicationThreadNative extends Binder
implements IApplicationThread
......
由以上代码可以看出 ApplicationThread 继承了 ApplicationThreadNative ,而ApplicationThreadNative 继承了Binder并且实现了IApplicationThread 接口,但是在它内部,还有一个内部类ApplicationThreadProxy,实现如下:
【ApplicationThreadProxy 类】
class ApplicationThreadProxy implements IApplicationThread
private final IBinder mRemote;
public ApplicationThreadProxy(IBinder remote)
mRemote = remote;
public final IBinder asBinder()
return mRemote;
//☆☆☆☆☆ 重点!!!!!
public final void schedulePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges) throws RemoteException
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(token);
data.writeInt(finished ? 1 : 0);
data.writeInt(userLeaving ? 1 :0);
data.writeInt(configChanges);
mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
public final void scheduleStopActivity(IBinder token, boolean showWindow,
int configChanges) throws RemoteException
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(token);
data.writeInt(showWindow ? 1 : 0);
data.writeInt(configChanges);
mRemote.transact(SCHEDULE_STOP_ACTIVITY_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
......
ApplicationThreadProxy 也是系统为AIDL文件自动生成的代理类。
通过以上分析可知,ApplicationThreadNative就是IApplicationThread的实现者,由于ApplicationThreadNative被系统定义为抽象类,所以ApplicationThread就成了IApplicationThread的最终实现者。
Step 7. ActivityThread 内部类 ApplicationThread
绕了一大圈,Activity的启动过程最终回到了ApplicationThread ,它通过 scheduleLaunchActivity
方法来启动 Activity,代码如下:
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
int procState, Bundle state, List<ResultInfo> pendingResults,
List<Intent> 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);
在 ApplicationThread中,此方法实现非常简单,就是发送一个Activity的消息交由 Handle 处理(最后一行代码),这个Handle实现于 ActivityThread 内部,名为H。
Step 8. ActivityThread 内部 Handle
此Handle对消息处理的实现:
public static final int LAUNCH_ACTIVITY = 100;
public static final int PAUSE_ACTIVITY = 101;
public static final int PAUSE_ACTIVITY_FINISHING= 102;
public static final int STOP_ACTIVITY_SHOW = 103;
public static final int STOP_ACTIVITY_HIDE = 104;
public static final int SHOW_WINDOW = 105;
public static final int HIDE_WINDOW = 106;
public static final int RESUME_ACTIVITY = 107;
......
public void handleMessage(Message msg)
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what)
case LAUNCH_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
//☆☆☆☆☆ 重点!!!!!
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(r);
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;
......
非常熟悉的Handle实现方法,注意在ApplicationThread发送消息的标志是H.LAUNCH_ACTIVITY,直接查看handleMessage
方法中对应的处理代码。此时可以发现,Activity的启动过程是由ActivityThread的handleLaunchActivity
方法实现,查看其代码:
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);
//☆☆☆☆☆ 重点!!!!!
Activity a = performLaunchActivity(r, customIntent);
if (a != null)
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed);
......
总算到了最后一步,从以上代码可以看出,performLaunchActivity方法最终完成了Activity对象的创建和启动过程,并且ActivityThread通过 handleResumeActivity方法来调用被启动Activity的onResume这一生命周期方法。
后半部分时序图如下:
接下来详细介绍performLaunchActivity方法完成的五大事件:
(1)从ActivityClientRecord中获取待启动的Activity的组件信息
【ActivityThread 类的 performLaunchActivity方法中】
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null)
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
ComponentName component = r.intent.getComponent();
if (component == null)
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
if (r.activityInfo.targetActivity != null)
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
(2)从Instrumentation 的 newActivity 方法使用类加载器创建 Activity对象
【ActivityThread 类的 performLaunchActivity方法中】
Activity activity = null;
try
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
//☆☆☆
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
if (r.state != null)
r.state.setClassLoader(cl);
catch (Exception e)
if (!mInstrumentation.onException(activity, e))
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
至于 Instrumentation 的 newActivity,它的实现比较简单,就是通过类加载器创建Activity对象,代码如下:
【Instrumentation 类】
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException
return (Activity)cl.loadClass(className).newInstance();
(3)通过 LoadedAPK 的 makeApplication 方法来尝试创建 Application对象
【ActivityThread 类的 performLaunchActivity方法中】
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
查看LoadedAPK 的 makeApplication 方法具体实现:
【LoadedAPK 类】
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation)
if (mApplication != null)
return mApplication;
Application app = null;
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null))
appClass = "android.app.Application";
try
java.lang.ClassLoader cl = getClassLoader();
ContextImpl appContext = new ContextImpl();
appContext.init(this, null, mActivityThread);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
catch (Exception e)
if (!mActivityThread.mInstrumentation.onException(app, e))
throw new RuntimeException(
"Unable to instantiate application " + appClass
+ ": " + e.toString(), e);
mActivityThread.mAllApplications.add(app);
mApplication = app;
if (instrumentation != null)
try
instrumentation.callApplicationOnCreate(app);
catch (Exception e)
if (!instrumentation.onException(app, e))
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
return app;
从此方法的实现可以看出,如果Application已经被创建过,就不会再创建,以为者一个应用只有一个Application对象。Application对象的创建也是通过Instrumentation完成的,这个过程和Activity对象的创建一样,都是通过类加载器实现的。Application创建完毕后,系统会通过 Instrumentation 的 callApplicationOnCreate
来调用Application的 onCreate
方法。
(4)通过 ContextImpl对象并通过Activity的 attach 方法来完成一些重要数据的初始化
【ActivityThread 类的 performLaunchActivity方法中】
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config);
ContextImpl是一个很重要的数据结构,它是Context 的具体实现,Context中大部分逻辑都是由ContextImpl来实现的。ContextImpl是通过Activity的attach方法来和Activity建立关系的,除此之外,在attach方法中Activity还会完成Window的创建并建立自己和Window的关联,这样当Window接收到外部输入事件后就可以将事件传递给Activity。
(5)调用 Activity 的 onCreate方法
【ActivityThread 类的 performLaunchActivity方法中】
mInstrumentation.callActivityOnCreate(activity, r.state);
如上代码,Activity的onCreate
方法被调用,意味着Activity已经完成了整个启动过程!
二. Activity启动流程总时序图:
其实以上关于Activity底层的问题你不知道也可以写好代码,但是学习了解系统的底层工作原理,相当于学习Android操作系统,可以提高我们对操作系统在技术实现上的理解。如果学习Android使用方法相当于练习武功招式,那么学习底层工作原理就相当于修炼内功,haha,要知道高手之间过招比的是什么? 当然是看谁内功深厚啦~
最后,在此声明,以上内容总结于《Android艺术开发与探索》,时序图是自己归纳的,这个我参考了网上其它的博文讲解,但是跟书上稍有差别,大概是讲解的侧重点不同,如有错误,还请指正。
关于书上这个章节我看过起码5遍,但每次过了不久就忘了,所以此次总结下来,印象深刻一些,但是我感觉自己还是没有完全理解,只是了解了一个大致流程,以后再做补充吧。
检验一个知识点是否学会,写下来和讲出来恐怕是最有效的方法了。
希望对你们有帮助 :)
共同学习
以上是关于Android:图解Activity启动流程源码(整体流程)的主要内容,如果未能解决你的问题,请参考以下文章
Android 启动过程Activity 启动源码分析 ( ActivityThread 流程分析 二 )
framework之Activity启动流程(基于Android11源码)