概述
Activity作为Android的四大组件之一,Android主要的界面组成部分,用于直接跟用户进行交互操作,在面试中与Activity相关的知识也是经常被问到,如果你面试的高级岗位,那么对Activity的启动和绘制流程就必须的熟悉,本文将从Activity的启动流程来分析Activity。启动Activity的方式大致有两种:一种是在桌面点击应用程序的图标,进入应用程序的主界面;另一种是在应用程序中,进入一个新的Activity。前者属于launcher启动的范畴,本文不做具体的深入分析,后面会具体的分析,不过它的实质是从一个应用的Activity进入另一个应用Activity。
因此,不管是从桌面进入应用主界面,还是在应用里进入一个新的Activity,最终都会调用Activity$startActivity方法。
值得注意的是,Android 5.0,7.0等版本中启动Activity的流程略微有一些细小的改变,但这并不妨碍我们理解Activity的启动流程。
Binder机制
首先,我们要介绍下Android系统中一个重要的内容:Binder机制。为了满足进程间的通信,Android系统将进程分为了用户(Zygote)进程和系统(SystemServer)进程以及各种应用进程等,为了能够实现各种进程之间的通讯,Android系统采用了自己的进程间通讯方式Binder机制。其中主要涉及到了四种角色:Binder Client,Binder Server,Binder Manager, Binder driver。各种角色之间的关系可以参考下面这张图的介绍:
启动Activity流程解读
当我们使用startActivity() 启动另一个Activity后,主要会调用以下的一些函数。
MyActivity.startActivity()
Activity.startActivity()
Activity.startActivityForResult
Instrumentation.execStartActivty
ActivityManagerNative.getDefault().startActivityAsUser()
首先,我们来看一下startActivity()函数的源码:
@Override
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
startActivityForResult(intent, -1);
}
}
其实,startActivity还有几个其他重载的方法,但是最终都会执行到Activity$startActivityForResult方法。如果是调用startActivity(intent)启动Activity,那么requestCode参数则传入-1,表示需要返回Activity的数据。
到此继续往下看,startActivityForResult方法的具体实现如下:
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) {
// 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;
}
cancelInputsAndStartExitTransition(options);
// TODO Consider clearing/flushing other event sources and events for child windows.
} else {
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);
}
}
}
在上面的代码中,mParent进行了一个判Null操作,可以发现由于我们是第一次启动Activity,所以这里的mParent为空,所以会执行if分之,然后调用mInstrumentation.execStartActivity方法,并且这里需要注意的是,有一个判断逻辑。即:
if (requestCode >= 0) {
mStartedActivity = true;
}
前面说过,调用startActivityForResult的时候只有requestCode的值大于等于0,onActivityResult才会被回调。
Instrumentation
然后我们看一下mInstrumentation.execStartActivity方法的具体实现。在看execStartActivity方法之前,首先看一下Instrumentation,Instrumentation是android系统中启动Activity的一个实际操作类,也就是说Activity在应用进程端的启动实际上就是Instrumentation执行的。那为什么是这样呢?实际上acitivty的启动分为应用进程端的启动和SystemServer服务进程端的启动的,多个应用进程相互配合最终完成了Activity在系统中的启动的,而在应用进程端的启动实际的操作类就是Intrumentation来执行的。
为了方便理解,我们直接看execStartActivity函数源码:
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) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=0; i
final ActivityMonitor am = mActivityMonitors.get(i);
ActivityResult result = null;
if (am.ignoreMatchingSpecificIntents()) {
result = am.onStartActivity(intent);
}
if (result != null) {
am.mHits++;
return result;
} else if (am.match(who, null, intent)) {
am.mHits++;
if (am.isBlocking()) {
return requestCode >= 0 ? am.getResult() : null;
}
break;
}
}
}
}
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;
}
如上,execStartActivity主要有以下几个参数:
this,为启动Activity的对象;
contextThread,为Binder对象,是主进程的context对象;
token,也是一个Binder对象,指向了服务端一个ActivityRecord对象;
target,为启动的Activity;
intent,启动的Intent对象;
requestCode,请求码;
options,参数;
通过,execStartActivity方法可以发现,该方法主要调用ActivityManager.getService()方法,继续查看ActivityManager$getService源码。
/**
* @hide
*/
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;
}
};
//...code
}
可以发现,IActivityManager.Stub.asInterface(b),那么继续看asInterface方法的实现:
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ActivityManagerProxy(obj);
}
asInterface()返回一个ActivityManagerProxy对象,ActivityManagerProxy继承与IActivityManager,到了这里就引出了我们android系统中很重要的一个概念:Binder机制。
IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE)
如上,是获取一个关联了系统服务ActivityManagerService的Binder对象。所以,IBinder最终和ActivityManagerService形成了绑定关系。
public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
}
所以,ActivityManager.getService().startActivity(…)的最终调用的是ActivityManagerService的startActivity方法。
ActivityManagerService启动Activity
首先来看一下,ActivityManagerService$startActivity的相关源码。@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}