一直在使用Activity,今天开始就来看下这个Activity究竟是如何启动的。
Activity分为根Activity和应用内Activity,根Activity就是我们点击手机屏幕上的icon时启动的Activity,应用内Activity就是我们应用内部跳转的Activity。今天我们从根Activity开始分析它的启动流程。
点击手机屏幕上的icon,其实就是android的Launcher接受点击事件,然后启动应用activity的过程,至于启动哪个Activity,这个在AndroidManifest.xml文件文件中进行配置:
<activity android:name="com.rock.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
Launcher在启动应用的时候就会去启动<action android:name="android.intent.action.MAIN"/>
并且<category android:name="android.intent.category.LAUNCHER"/>
的Activity。可能会有疑问,Launcher怎么会有应用的这些信息呢?应用在安装完成之后,Launcher在界面上显示应用的icon,Launcher就会有应用对应的信息,具体可以去看下应用的安装过程。
Launcher继承Acitivity,故Launcher启动根Activity的时候调用startActivity(intent)会调用Activity的startActivity(intent),接下来就从Activity的startActivity(intent)开始逐步分析Activity的启动流程。由于整个流程比较长,故启动流程会多分几个篇。
1. Activity.startActivity(intent)
这个很好理解了,就是构造intent参数,然后调用startActivity函数了
public void startActivity(Intent intent) {
startActivityForResult(intent, -1);
}
可以看到,startActivity(intent)
接下来会调用startActivityForResult(intent, -1)
,requestCode为-1说明不需要获取启动Activity的结果。
2. startActivityForResult(intent, -1)
public void startActivityForResult(Intent intent, int requestCode) {
if (mParent == null) {
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
mStartedActivity = true;
}
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
mParent为空,故会执行mInstrumentation.execStartActivity这个函数。暂时不用纠结mInstrumentation,只需要知道Instrumentation
是用来监控应用和系统的交互即可,接下来,Activity的启动会进入Instrumentation中。
3. Instrumentation.execStartActivity
执行到这个函数,参数突然多起来,看下它的函数原型:
public ActivityResult execStartActivity(Context who, IBinder
contextThread, IBinder token, Activity target, Intent intent, int questCode)
{
IApplicationThread whoThread = (IApplicationThread) contextThread;
......
try {
intent.setAllowFds(false);
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
null, 0, token, target != null ? target.mEmbeddedID : null,
requestCode, false, false, null, null, false);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
}
return null;
}
一下子感觉参数多了起来,没关系,一个一个参数分析。who是调用这个函数的Activity的Context;contextThread是应用和ActivityManangerService的桥梁,负责引用与ActivityManagerService之间的通信;token是调用这个函数的Activity的标识;tartget就是调用这个函数的Activity的实例;intent就是我们启动时传递的intent;requestCode就是调用startActivityForResult时传递的requestCode,从前面的分析可知,此处的requestCode为-1。接下来要进入ActivityManagerNative.getDefault() .startActivity
这个函数了。看下ActivityManagerNative.getDefault()这个函数:
#1
static public IActivityManager getDefault() {
return gDefault.get();
}
#2
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;
}
};
#3
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);
}
代码片段#2表明gDefault是ActivityManagerService的一个单例,通过调用gDefault.get()获取的是ActivityManagerService的代理对象ActivityManagerProxy,也就是说ActivityManagerNative.getDefault().startActivity最终startActivity的调用是在ActivityManangerProxy中代理完成。这里涉及到Android的binder通信机制,后面再具体分析,反正记得这里面涉及到binder通信,最终startAcivity实在ActivityManangerService中完成的。ok,说了这么多,ActivityManagerProxy究竟有没有这个函数呢?
4. ActivityManagerProxy.startActivity
public int startActivity(IApplicationThread caller, Intent intent,
String resolvedType, Uri[] grantedUriPermissions, int grantedMode,
IBinder resultTo, String resultWho,
int requestCode, boolean onlyIfNeeded,
boolean debug, String profileFile, ParcelFileDescriptor profileFd,
boolean autoStopProfiler) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
intent.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeTypedArray(grantedUriPermissions, 0);
data.writeInt(grantedMode);
data.writeStrongBinder(resultTo);
data.writeString(resultWho);
data.writeInt(requestCode);
data.writeInt(onlyIfNeeded ? 1 : 0);
data.writeInt(debug ? 1 : 0);
data.writeString(profileFile);
if (profileFd != null) {
data.writeInt(1);
profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
data.writeInt(0);
}
data.writeInt(autoStopProfiler ? 1 : 0);
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
int result = reply.readInt();
reply.recycle();
data.recycle();
return result;
}
不要被这么多的参数吓到,仔细分析下,参数很好理解。caller就是负责应用和ActivityManangerService进行交互的ApplicationThread;intent就是我们传递的intent;resolveType为mime类型,在这里为null;grantedUriPermissions通过分析可知道在这里为null;grandMode在这里为0;resultTo标识启动这个Activity的Activity;resultWho表示应用的包名;后续的几个参数,boolean类型的均为false,非原始类型的数据均为null。
将这些数据全部写入Parcel类型data对象后,调用mRemote.transact函数进行跨进程通信,使ActivityManangerService执行startActivity的操作。下一节将会分析这一具体的流程。