Zygote是什么?有什么作用?
Android系统底层基于Linux Kernel, 当Kernel启动过程会创建init进程, 该进程是所有用户空间的鼻祖, init进程会启动ServiceManager(Binder服务管家)、 Zygote进程(Java进程的鼻祖)。Zygote进程会创建 system_server进程以及各种App进程。
Zygote进程:是Android系统的首个Java进程,Zygote是所有Java进程的父进程,包括 system_server进程以及所有的App进程都是Zygote的子进程,注意这里说的是子进程,而非子线程。
我们都知道,每一个App其实都是
- 一个单独的Dalvik虚拟机
- 一个单独的进程
所以当系统里面的第一个Zygote进程运行之后,在这之后再开启App,就相当于开启一个新的进程。而为了实现资源共用和更快的启动速度,Android系统开启新进程的方式,是通过fork第一个Zygote进程实现的。所以说,除了第一个Zygote进程,其他应用所在的进程都是Zygote的子进程,这下你明白为什么这个进程叫“受精卵”了吧?因为就像是一个受精卵一样,它能快速的分裂,并且产生遗传物质一样的细胞!
SystemServer是什么?有什么作用?它与zygote的关系是什么?
首先我要告诉你的是,SystemServer也是一个进程,而且是由zygote进程fork出来的。
知道了SystemServer的本质,我们对它就不算太陌生了,这个进程是Android Framework里面两大非常重要的进程之一—另外一个进程就是上面的zygote进程。
为什么说SystemServer非常重要呢?因为系统里面重要的服务都是在这个进程里面开启的,比如
ActivityManagerService、PackageManagerService、WindowManagerService等等,看着是不是都挺眼熟的?
那么这些系统服务是怎么开启起来的呢?
在zygote开启的时候,会调用ZygoteInit.main()进行初始化
public static void main(String argv[]) {
...ignore some code...
//在加载首个zygote的时候,会传入初始化参数,使得startSystemServer = true
boolean startSystemServer = false;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
socketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
...ignore some code...
//开始fork我们的SystemServer进程
if (startSystemServer) {
startSystemServer(abiList, socketName);
}
...ignore some code...
}
ActivityManagerService是什么?什么时候初始化的?有什么作用?
ActivityManagerService,简称AMS,服务端对象,负责系统中所有Activity的生命周期。
ActivityManagerService进行初始化的时机很明确,就是在SystemServer进程开启的时候,就会初始化ActivityManagerService。从下面的代码中可以看到
public final class SystemServer {
//zygote的主入口
public static void main(String[] args) {
new SystemServer().run();
}
public SystemServer() {
// Check for factory test mode.
mFactoryTestMode = FactoryTest.getMode();
}
private void run() {
...ignore some code...
//加载本地系统服务库,并进行初始化
System.loadLibrary("android_servers");
nativeInit();
// 创建系统上下文
createSystemContext();
//初始化SystemServiceManager对象,下面的系统服务开启都需要调用SystemServiceManager.startService(Class<T>),这个方法通过反射来启动对应的服务
mSystemServiceManager = new SystemServiceManager(mSystemContext);
//开启服务
try {
startBootstrapServices();
startCoreServices();
startOtherServices();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
}
...ignore some code...
}
//初始化系统上下文对象mSystemContext,并设置默认的主题,mSystemContext实际上是一个ContextImpl对象。调用ActivityThread.systemMain()的时候,会调用ActivityThread.attach(true),而在attach()里面,则创建了Application对象,并调用了Application.onCreate()。
private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
}
//在这里开启了几个核心的服务,因为这些服务之间相互依赖,所以都放在了这个方法里面。
private void startBootstrapServices() {
...ignore some code...
//初始化ActivityManagerService
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
//初始化PowerManagerService,因为其他服务需要依赖这个Service,因此需要尽快的初始化
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
// 现在电源管理已经开启,ActivityManagerService负责电源管理功能
mActivityManagerService.initPowerManagement();
// 初始化DisplayManagerService
mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
//初始化PackageManagerService
mPackageManagerService = PackageManagerService.main(mSystemContext, mInstaller,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
...ignore some code...
}
}
经过上面这些步骤,我们的ActivityManagerService对象已经创建好了,并且完成了成员变量初始化。而且在这之前,调用createSystemContext()创建系统上下文的时候,也已经完成了mSystemContext和ActivityThread的创建。注意,这是系统进程开启时的流程,在这之后,会开启系统的Launcher程序,完成系统界面的加载与显示。
你是否会好奇,我为什么说AMS是服务端对象?下面我给你介绍下Android系统里面的服务器和客户端的概念。
其实服务器客户端的概念不仅仅存在于Web开发中,在Android的框架设计中,使用的也是这一种模式。服务器端指的就是所有App共用的系统服务,比如我们这里提到的ActivityManagerService,和前面提到的PackageManagerService、WindowManagerService等等,这些基础的系统服务是被所有的App公用的,当某个App想实现某个操作的时候,要告诉这些系统服务,比如你想打开一个App,那么我们知道了包名和MainActivity类名之后就可以打开
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
ComponentName cn = new ComponentName(packageName, className);
intent.setComponent(cn);
startActivity(intent);
但是,我们的App通过调用startActivity()并不能直接打开另外一个App,这个方法会通过一系列的调用,最后还是告诉AMS说:“我要打开这个App,我知道他的住址和名字,你帮我打开吧!”所以是AMS来通知zygote进程来fork一个新进程,来开启我们的目标App的。这就像是浏览器想要打开一个超链接一样,浏览器把网页地址发送给服务器,然后还是服务器把需要的资源文件发送给客户端的。
知道了Android Framework的客户端服务器架构之后,我们还需要了解一件事情,那就是我们的App和AMS(SystemServer进程)还有zygote进程分属于三个独立的进程,他们之间如何通信呢?
App与AMS通过Binder进行IPC通信,AMS(SystemServer进程)与zygote通过Socket进行IPC通信。
那么AMS有什么用呢?在前面我们知道了,如果想打开一个App的话,需要AMS去通知zygote进程,除此之外,其实所有的Activity的开启、暂停、关闭都需要AMS来控制,所以我们说,AMS负责系统中所有Activity的生命周期。
在Android系统中,任何一个Activity的启动都是由AMS和应用程序进程(主要是ActivityThread)相互配合来完成的。AMS服务统一调度系统中所有进程的Activity启动,而每个Activity的启动过程则由其所属的进程具体来完成。
这样说你可能还是觉得比较抽象,没关系,下面有一部分是专门来介绍AMS与ActivityThread如何一起合作控制Activity的生命周期的。
Launcher是什么?什么时候启动的?
当我们点击手机桌面上的图标的时候,App就由Launcher开始启动了。但是,你有没有思考过Launcher到底是一个什么东西?
Launcher本质上也是一个应用程序,和我们的App一样,也是继承自Activity
packages/apps/Launcher2/src/com/android/launcher2/Launcher.java
public final class Launcher extends Activity
implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,
View.OnTouchListener {
}1234
Launcher实现了点击、长按等回调接口,来接收用户的输入。既然是普通的App,那么我们的开发经验在这里就仍然适用,比如,我们点击图标的时候,是怎么开启的应用呢?如果让你,你怎么做这个功能呢?捕捉图标点击事件,然后startActivity()发送对应的Intent请求呗!是的,Launcher也是这么做的,就是这么easy!
那么到底是处理的哪个对象的点击事件呢?既然Launcher是App,并且有界面,那么肯定有布局文件呀,是的,我找到了布局文件launcher.xml
为了方便查看,我删除了很多代码,从上面这些我们应该可以看出一些东西来:Launcher大量使用标签来实现界面的复用,而且定义了很多的自定义控件实现界面效果,dock_divider从布局的参数声明上可以猜出,是底部操作栏和上面图标布局的分割线,而paged_view_indicator则是页面指示器,和App首次进入的引导页下面的界面引导是一样的道理。当然,我们最关心的是Workspace这个布局,因为注释里面说在这里面包含了5个屏幕的单元格,想必你也猜到了,这个就是在首页存放我们图标的那五个界面(不同的ROM会做不同的DIY,数量不固定)。
CellLayout确实是继承自ViewGroup。在CellLayout里面,只放了一个子View,那就是ShortcutAndWidgetContainer。从名字也可以看出来,ShortcutAndWidgetContainer这个类就是用来存放快捷图标和Widget小部件的,那么里面放的是什么对象呢?
在桌面上的图标,使用的是BubbleTextView对象,这个对象在TextView的基础之上,添加了一些特效,比如你长按移动图标的时候,图标位置会出现一个背景(不同版本的效果不同),所以我们找到BubbleTextView对象的点击事件,就可以找到Launcher如何开启一个App了。
除了在桌面上有图标之外,在程序列表中点击图标,也可以开启对应的程序。这里的图标使用的不是BubbleTextView对象,而是PagedViewIcon对象,我们如果找到它的点击事件,就也可以找到Launcher如何开启一个App。
其实说这么多,和今天的主题隔着十万八千里,上面这些东西,你有兴趣就看,没兴趣就直接跳过,不知道不影响这篇文章阅读。
BubbleTextView的点击事件在哪里呢?我来告诉你:在Launcher.onClick(View v)里面。
public void onClick(View v) {
...ignore some code...
Object tag = v.getTag();
if (tag instanceof ShortcutInfo) {
// Open shortcut
final Intent intent = ((ShortcutInfo) tag).intent;
int[] pos = new int[2];
v.getLocationOnScreen(pos);
intent.setSourceBounds(new Rect(pos[0], pos[1],
pos[0] + v.getWidth(), pos[1] + v.getHeight()));
//开始开启Activity咯~
boolean success = startActivitySafely(v, intent, tag);
if (success && v instanceof BubbleTextView) {
mWaitingForResume = (BubbleTextView) v;
mWaitingForResume.setStayPressed(true);
}
} else if (tag instanceof FolderInfo) {
//如果点击的是图标文件夹,就打开文件夹
if (v instanceof FolderIcon) {
FolderIcon fi = (FolderIcon) v;
handleFolderClick(fi);
}
} else if (v == mAllAppsButton) {
...ignore some code...
}
}
从上面的代码我们可以看到,在桌面上点击快捷图标的时候,会调用
startActivitySafely(v, intent, tag);
那么从程序列表界面,点击图标的时候会发生什么呢?实际上,程序列表界面使用的是AppsCustomizePagedView对象,所以我在这个类里面找到了onClick(View v)。
public class AppsCustomizePagedView extends PagedViewWithDraggableItems implements
View.OnClickListener,View.OnKeyListener,DragSource,PagedViewIcon.PressedCallback,
PagedViewWidget.ShortPressListener, LauncherTransitionable {
@Override
public void onClick(View v) {
...
if (v instanceof PagedViewIcon) {
mLauncher.updateWallpaperVisibility(true);
mLauncher.startActivitySafely(v, appInfo.intent, appInfo);
} else if (v instanceof PagedViewWidget) {
...ignore some code..
}
}
}
可以看到,调用的是
mLauncher.startActivitySafely(v, appInfo.intent, appInfo);
和上面一样!这叫什么?这叫殊途同归!
所以咱们现在又明白了一件事情:不管从哪里点击图标,调用的都是Launcher.startActivitySafely()。
- 下面我们就可以一步步的来看一下Launcher.startActivitySafely()到底做了什么事情。
boolean startActivitySafely(View v, Intent intent, Object tag) {
boolean success = false;
try {
success = startActivity(v, intent, tag);
} catch (ActivityNotFoundException e) {
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
}
return success;
}
调用了startActivity(v, intent, tag)
boolean startActivity(View v, Intent intent, Object tag) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
boolean useLaunchAnimation = (v != null) &&
!intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
if (useLaunchAnimation) {
if (user == null || user.equals(android.os.Process.myUserHandle())) {
startActivity(intent, opts.toBundle());
} else {
launcherApps.startMainActivity(intent.getComponent(), user,
intent.getSourceBounds(),
opts.toBundle());
}
} else {
if (user == null || user.equals(android.os.Process.myUserHandle())) {
startActivity(intent);
} else {
launcherApps.startMainActivity(intent.getComponent(), user,
intent.getSourceBounds(), null);
}
}
return true;
} catch (SecurityException e) {
...
}
return false;
}
这里会调用Activity.startActivity(intent, opts.toBundle()),这个方法熟悉吗?这就是我们经常用到的Activity.startActivity(Intent)的重载函数。而且由于设置了
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
所以这个Activity会添加到一个新的Task栈中,而且,startActivity()调用的其实是startActivityForResult()这个方法。
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}
所以我们现在明确了,Launcher中开启一个App,其实和我们在Activity中直接startActivity()基本一样,都是调用了Activity.startActivityForResult()。
Instrumentation是什么?和ActivityThread是什么关系?
还记得前面说过的Instrumentation对象吗?每个Activity都持有Instrumentation对象的一个引用,但是整个进程只会存在一个Instrumentation对象。当startActivityForResult()调用之后,实际上还是调用了mInstrumentation.execStartActivity()
public void startActivityForResult(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());
}
...ignore some code...
} else {
if (options != null) {
//当现在的Activity有父Activity的时候会调用,但是在startActivityFromChild()内部实际还是调用的mInstrumentation.execStartActivity()
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
...ignore some code...
}
下面是mInstrumentation.execStartActivity()
的实现
public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
...ignore some code...
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess();
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) {
}
return null;
}
所以当我们在程序中调用startActivity()的 时候,实际上调用的是Instrumentation的相关的方法。
Instrumentation意为“仪器”,我们先看一下这个类里面包含哪些方法吧
我们可以看到,这个类里面的方法大多数和Application和Activity有关,是的,这个类就是完成对Application和Activity初始化和生命周期的工具类。比如说,我单独挑一个callActivityOnCreate()
让你看看
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
activity.performCreate(icicle);
postPerformCreate(activity);
}
对activity.performCreate(icicle);这一行代码熟悉吗?这一行里面就调用了传说中的Activity的入口函数onCreate(),不信?接着往下看Activity.performCreate()
final void performCreate(Bundle icicle) {
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
没骗你吧,onCreate在这里调用了吧。但是有一件事情必须说清楚,那就是这个Instrumentation类这么重要,为啥我在开发的过程中,没有发现他的踪迹呢?
是的,Instrumentation这个类很重要,对Activity生命周期方法的调用根本就离不开他,他可以说是一个大管家,但是,这个大管家比较害羞,是一个女的,管内不管外,是老板娘~
那么你可能要问了,老板是谁呀?
老板当然是大名鼎鼎的ActivityThread了!
public final class ActivityThread {//没有继承或者实现其他类。
final ApplicationThread mAppThread = new ApplicationThread();
public ApplicationThread getApplicationThread(){
return mAppThread;
}
//ActivityThread的内部类ApplicationThread
private class ApplicationThread extends ApplicationThreadNative {
......
}
}
ApplicationThreadNative
就是相当于AIDL通讯中的Stub,也就是服务端,ApplicationThreadProxy
即AIDL通讯中的Proxy,也就是客户端。所以ApplicationThread
是通讯的具体实现类。
ActivityThread你都没听说过?那你肯定听说过传说中的UI线程吧?是的,这就是UI线程。我们前面说过,App和AMS是通过Binder传递信息的,那么ActivityThread就是专门与AMS的外交工作的。
AMS说:“ActivityThread,你给我暂停一个Activity!”
ActivityThread就说:“没问题!”然后转身和Instrumentation说:“老婆,AMS让暂停一个Activity,我这里忙着呢,你快去帮我把这事办了把~”
于是,Instrumentation就去把事儿搞定了。
所以说,AMS是董事会,负责指挥和调度的,ActivityThread是老板,虽然说家里的事自己说了算,但是需要听从AMS的指挥,而Instrumentation则是老板娘,负责家里的大事小事,但是一般不抛头露面,听一家之主ActivityThread的安排。
如何理解AMS和ActivityThread之间的Binder通信?
前面我们说到,在调用startActivity()的时候,实际上调用的是
mInstrumentation.execStartActivity()
但是到这里还没完呢!里面又调用了下面的方法
ActivityManagerNative.getDefault().startActivity()
这里的ActivityManagerNative.getDefault
返回的就是ActivityManagerService
的远程接口,即ActivityManagerProxy
。
怎么知道的呢?往下看
public abstract class ActivityManagerNative extends Binder implements IActivityManager{
//从类声明上,可以看到ActivityManagerNative是Binder的一个子类,而且实现了IActivityManager接口
static public IActivityManager getDefault() {
return gDefault.get();
}
//通过单例模式获取一个IActivityManager对象,这个对象通过asInterface(b)获得
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
IActivityManager am = asInterface(b);
return am;
}
};
//最终返回的还是一个ActivityManagerProxy对象
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
//这里面的Binder类型的obj参数会作为ActivityManagerProxy的成员变量保存为mRemote成员变量,负责进行IPC通信
return new ActivityManagerProxy(obj);
}
}
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeString(callingPackage);
intent.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(resultTo);
data.writeString(resultWho);
data.writeInt(requestCode);
data.writeInt(startFlags);
if (profilerInfo != null) {
data.writeInt(1);
profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
data.writeInt(0);
}
if (options != null) {
data.writeInt(1);
options.writeToParcel(data, 0);
} else {
data.writeInt(0);
}
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
int result = reply.readInt();
reply.recycle();
data.recycle();
return result;
}
再看ActivityManagerProxy.startActivity()
,在这里面做的事情就是IPC通信,利用Binder对象,调用transact(),把所有需要的参数封装成Parcel对象,向AMS发送数据进行通信。
ActivityManagerProxy经过Binder IPC,进入ActivityManagerNative。接下来程序进入了system_servr进程,开始继续执行。接下来程序进入了system_servr进程,开始继续执行。
transact
方法是一个本地方法;它的实现在native层,具体来说在frameworks/base/core/jni/android_util_Binder.cpp
文件,里面进行了一系列的函数调用它最终调用到了talkWithDriver
函数;看这个函数的名字就知道,通信过程要交给驱动完成了;这个函数最后通过ioctl
系统调用,Client进程陷入内核态,Client调用add
方法的线程挂起等待返回;驱动完成一系列的操作之后唤醒Server进程,调用了Server进程本地对象的onTransact
函数(实际上由Server端线程池完成)。Binder本地对象的onTransact
方法(这里就是Stub
类里面的此方法)
ActivityManagerService本质就是一个Binder,并且实体在服务端。AMS在远端操作着Activity的生命周期。这个进程由SystemServer进程fork出来。
ActivityThread。大家都知道ActivityThread就是应用的UI线程,main方法就是整个应用的入口。ActivityThread本质并不是一个线程,他只是依附着主线程存在。ActivityThread通过和AMS进行IPC通信来共同管理Activity的生命周期。在后面我准备写一篇关于Handle的续篇,里面还会提到他,因为主线程里面的Looper就是在这里init的。
ApplicationThread。它是ActivityThread的内部类,本质上ActivityThread是通过它来进行和AMS的IPC通信的。它的本质也是一个Binder!只不过这次他的实体放在客户端,AMS通过他的代理类ApplicationThreadProxy来和ApplicationThread通信。
Instrumentation。这个类我在看完第一遍书的时候感觉操作调用链里面的最外层。因为最后一步Activity实例对象的生成和onCreat()方法的调用最终是来自这个类的。其实这个类是ActivityThread想要进行的操作的具体操作类。这个类是全局的,并且每个Acitivity里面都拥有一个它的引用。
对Binder的理解
Binder本质上只是一种底层通信方式,和具体服务没有关系。为了提供具体服务,Server必须提供一套接口函数以便Client通过远程访问使用各种服务。这时通常采用Proxy设计模式:将接口函数定义在一个抽象类中,Server和Client都会以该抽象类为基类实现所有接口函数,所不同的是Server端是真正的功能实现,而Client端是对这些函数远程调用请求的包装。
为了更方便的说明客户端和服务器之间的Binder通信,下面以ActivityManagerServices和他在客户端的代理类ActivityManagerProxy为例。
ActivityManagerServices和ActivityManagerProxy都实现了同一个接口——IActivityManager。
ActivityManagerNative.getDefault()就是ActivityManagerService的代理类!AMS和代理类本质上都是IActivityManager的实现类。
class ActivityManagerProxy implements IActivityManager{}
public final class ActivityManagerService extends ActivityManagerNative{}
public abstract class ActivityManagerNative extends Binder implements IActivityManager{}
虽然都实现了同一个接口,但是代理对象ActivityManagerProxy并不会对这些方法进行真正地实现,ActivityManagerProxy只是通过这种方式对方法的参数进行打包(因为都实现了相同接口,所以可以保证同一个方法有相同的参数,即对要传输给服务器的数据进行打包),真正实现的是ActivityManagerService。
但是这个地方并**不是直接由客户端传递给服务器,而是通过Binder驱动进行中转。其实我对Binder驱动并不熟悉,我们就把他当做一个中转站就OK,客户端调用ActivityManagerProxy接口里面的方法,把数据传送给Binder驱动,然后Binder驱动就会把这些东西转发给服务器的ActivityManagerServices,由ActivityManagerServices去真正的实施具体的操作。
但是Binder只能传递数据,并不知道是要调用ActivityManagerServices的哪个方法,所以在数据中会添加方法的唯一标识码,比如前面的startActivity()方法:
public int startActivity() throws RemoteException {
...
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
}
上面的START_ACTIVITY_TRANSACTION就是方法标示,data是要传输给Binder驱动的数据,reply则接受操作的返回值。
客户端:ActivityManagerProxy =====>Binder驱动=====> ActivityManagerService:服务器
而且由于继承了同样的公共接口类,ActivityManagerProxy提供了与ActivityManagerService一样的函数原型,使用户感觉不出Server是运行在本地还是远端,从而可以更加方便的调用这些重要的系统服务。
但是!这里Binder通信是单方向的,即从ActivityManagerProxy指向ActivityManagerService的,如果AMS想要通知ActivityThread做一些事情,应该咋办呢?
还是通过Binder通信,不过是换了另外一对,换成了ApplicationThread和ApplicationThreadProxy。
客户端:ApplicationThread <=====Binder驱动<===== ApplicationThreadProxy:服务器
他们也都实现了相同的接口IApplicationThread
private class ApplicationThread extends ApplicationThreadNative {}
public abstract class ApplicationThreadNative extends Binder implements IApplicationThread{}
class ApplicationThreadProxy implements IApplicationThread {}12345
AMS接收到客户端的请求之后,会如何开启一个Activity?
ActivityStack(AMS中)。很好懂,一个Activity栈。但是这个ActivityStack是有两种类型的,一种叫系统ActivityStack(HomeTask),这一类的ActivityStack包含着Launcher(或者有其他我不知道的),还有一种是普通应用的ActivityStack(安卓中Task这个概念的具体实现形式),其实就是一个Task(任务栈)。这个类是由AMS来管理,AMS通过这个数据结构来得知Activity的状态。
ActivityStackSuperisor(AMS中)。加了一个单词,就是Activity栈的管理者。这个类的作用就是管理栈,并且通过ActivityStack来获得要启动的activity的信息。
ActivityRecord。这个就是上面说的服务端的Actiivty信息的载体类。并且也是服务端的类~这个类相当的重要,自始至终都贯穿在调用链里面,在安卓ActivityStack里面存储的并不是activity实例,其实就是这个ActivityRecord的实例。
ActivityClientRecord。这个和上面区别就是这个类是客户端activity信息的载体类。
TaskRecord。同样,这个类就是ActivityTask的信息记录类而已。
至此,点击桌面图标调用startActivity(),终于把数据和要开启Activity的请求发送到了AMS了。说了这么多,其实这些都在一瞬间完成了,下面咱们研究下AMS到底做了什么。
AMS收到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 options) {
//调用了startActivityAsUser,caller是我们的ApplicaitonThread
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, options,
UserHandle.getCallingUserId());
}
继续看这个startActivityAsUser()方法:
@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
enforceNotIsolatedCaller("startActivity");
userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,false, ALLOW_FULL_ONLY, "startActivity", null);
// TODO: Switch to user app stacks here. caller是我们的ApplicaitonThread
return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, options, userId, null, null);
}
startActivityAsUser()方法中调用了ActivityStackSupervisor的startActivityMayWait()方法。这里的目的就是想去通过栈的管理者来通过传进来的数据去改变栈,并且拿到被启动Activity的ActivityRecord实例。
在startActivityMayWait()里面,主要做了ActivityStack、ActivityInfo、 LaunchMode等等各种信息的初始化工作,然后就又调用了startActivityLocked()方法, 这个方法里面又做了一系列的变量初始化,初始启动的错误判断, UID检查之后,又调用了startActivityUncheckedLocked()方法。这个方法里面根据前面一系列的工作,确定了最终的LanuchMode,这个LaunchMode会在后面的函数被拿来进行判断,构建了一个新的Intent、ActivityInfo、ActivityTask。
ActivityStarter
startActivityMayWait方法根据Intent在系统中找到合适的应用的Activity,如果有多个Activity可选择,
则会弹出ResolverActivity让用户选择合适的应用。再调用startActivityLocked方法在startActivityLocked方法里,对传过来的参数做一些校验,然后创建ActivityRecord对象,再调用startActivityUnchecked方法启动Activity。
startActivityUnchecked方法负责调度ActivityRecord和Task,理解该方法是理解Actvity启动模式的关键。
startActivityUnchecked方法调度Task的算法非常复杂,和当前回退栈,要启动的acitivity的启动模式以及taskAffinity属性,启动activity时设置的intent的flag等诸多要素相关,intent的flag就有很多种情况,故此算法非常复杂,需要阅读源码并结合特定启动情况才能理解。
ActivityStarter的startActivityUnchecked() 方法调用ActivityStack的startActivityLocked()
//同时调用WindowManager准备App切换相关的工作
//ActivityStarter
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask){
//ActivityStack的startActivityLocked,同时调用WindowManager准备App切换相关的工作
mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
if (mDoResume) {
final ActivityRecord topTaskActivity =mStartActivity.task.topRunningActivityLocked();
if (!mTargetStack.isFocusable()|| (topTaskActivity != null && topTaskActivity.mTaskOverlay&& mStartActivity != topTaskActivity)) {
...
} else {
//最终调用ActivityStackSupervisor的resumeFocusedStackTopActivityLocked
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
}
}
}
ActivityStack
接下来调用ActivityStack的startActivityLocked将ActivityRecord加入到回退栈里。最终调用ActivityStackSupervisor
的resumeFocusedStackTopActivityLocked()
方法。
待启动Activity对应的Task为前台Task时,调用该Task对应ActivityStack的resumeTopActivityUncheckedLocked函数。
接着跟进ActivityStack
//ActivityStack
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
...
result = resumeTopActivityInnerLocked(prev, options);
return result;
}
private boolean resumeTopActivityInnerLocked(ActivityRecord prev,ActivityOptions options){
//mResumedActivity指向上一次启动的Activity(Launcher)
if (mResumedActivity != null) {
...
//通知Launcher进入pause状态
pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
}
if (pausing) {//Launcher已经暂停了
...
if (next.app != null && next.app.thread != null) {
//如果app已经启动过
//调用淘宝(待启动)Activity所在进程的优先级,保证其不被kill
mService.updateLruProcessLocked(next.app, true, null);
}
}
...
if (next.app != null && next.app.thread != null) {
//如果Intent不为空,调用NewIntent方法传入Intent
next.app.thread.scheduleNewIntent(next.newIntents, next.appToken, false);
//若淘宝已经启动,点击Home键返回到Launcher,再次从Launcher启动淘宝(或者第三方启动已开启的App)
next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
mService.isNextTransitionForward(), resumeAnimOptions);
} else {
//创建进程,冷启动Activity。或者已启动App,重新启动Activity
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
return true;
}
继续看resumeTopActivityInnerLocked(prev, options);这个方法太长了,我分析了一整天,终于所有体会吧。这个方法最终的作用是将启动者Activity的生命周期变成paused,这样之后被启动的Activity的实例创建了之后才能顺利的resumed。
resumeTopActivityInnerLocked函数非常繁琐,但整体来讲应该只有两个比较关键的地方:
- 判断是否已有Activity(mResumedActivity)启动(即Launcher,通过Launcher启动淘宝的),有则暂停该Activity
- 判断是否需要重新启动目标Activity,即Activity是否已经启动过。(例如保存在后台,应用切换)
2.AMS记录要启动的Activity信息,并且通知Launcher进入pause状态。
3.Launcher进入pause状态后,通知AMS已经paused了,可以启动淘宝了。
最终在函数的末尾会又调用ActivityStackSupervisor的startSpecificActivityLocked(next, true, true);方法。
创建进程
接下来的操作就比较重要了,创建进程,启动Activity。
//ActivityStackSupervisor
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 {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
|| !"android".equals(r.info.packageName)) {
app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
mService.mProcessStats);
}
//目标Activity的App已经启动(存在ActivityThread),则重启Activity
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
...
}
}
//如果进程不存在,则通过zygote创建应用进程。
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
从上面代码可以了解到startSpecificActivityLocked
为启动Activity的两种不同情况
- 例如从Launcher冷启动淘宝,则需要创建新进程,通过AMS调用Zygote(孕育天地)孵化应用进程。
- 如果淘宝App已经启动,例如从MainActivity跳转到LoginActivity,则通过
realStartActivityLocked
启动。
因为我们开头以Launcher启动淘宝为例子,所以我们硬着头皮继续分析AMS创建进程以及Activity的绑定过程。
上面分析到mService.startProcessLocked
,到了这里我们直接看启动线程的方法,中间的过程实在是略复杂。
4.淘宝App未开启过,所以AMS启动新的进程,并且在新进程中创建ActivityThread对象,执行其中的main函数方法。
Zygote进程孵化出新的应用进程后,通过反射执行ActivityThread类的main方法。在该方法里会先准备好Looper和消息队列,然后调用attach方法将应用进程绑定到AMS,然后进入loop循环,不断地读取消息队列里的消息,并分发消息。
至此,进程创建完毕,并且也有了主线程,剩下的便是启动Activity和关联Context等初始化操作了。
淘宝app主线程启动完毕后通知AMS,并传入applicationThread以便通讯。
//ActivityThread
public static void main(String[] args) {
...
//准备主线程的Looper,下篇博文分析Handler,Looper
Looper.prepareMainLooper();
//创建当前进程的ActivityThread
ActivityThread thread = new ActivityThread();
//将该进程绑定到AMS
thread.attach(false);
if (sMainThreadHandler == null) {
//保存进程对应的主线程Handler
sMainThreadHandler = thread.getHandler();
}
...
//进入主线程的消息循环
Looper.loop();
...
}
//上面说过,ApplicationThread是ActivityThread用来与AMS通讯的中介
final ApplicationThread mAppThread = new ApplicationThread();
private void attach(boolean system) {
if (!system) {
final IActivityManager mgr = ActivityManagerNative.getDefault();
//调用AMS的attachApplication方法,将ApplicationThread对象绑定至ActivityManagerService
//这样AMS就可以通过ApplicationThread代理对象控制应用进程
mgr.attachApplication(mAppThread);
} else {
...
}
}
AMS启动Activity小结
至此通过下图总结一下在AMS
启动Activity
的大致流程,各个方法函数像一台机器上的不同零件,各尽其责,分工明确。
虽然错综复杂,但是耦合性低,比如说启动模式需要优化,重新完善startActivityUnchecked
方法函数即可。
AMS.attachApplicationLocked() 关联Activity
在这个时候,虽然有了App进程和主线程,但是仍是一副空壳。
没有Activity信息,没有关联上下文,这时候就要请出AMS
来进行指挥。
因为主线程main入口通过attach
方法将 ApplicationThread
发送给 AMS
,所以通过applicationThread
这个桥梁来通知ActivityThread
创建/关联和启动Activity。
//AMS
@Override
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
//获取applicationThread的进程id(也就是淘宝应用进程)
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
通过Binder获取proxy(ApplicationThread )方的进程id,也就是获取目标(淘宝)进程的Pid。
//Binder
public static final native int getCallingPid();
接下来重点分析attachApplicationLocked
方法
//AMS
private final boolean attachApplicationLocked(IApplicationThread thread,int pid) {
ProcessRecord app;
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
} else {
app = null;
}
//因为进程由AMS启动,所以在AMS中一定会有ProcessRecord(进程记录)
//如果没有ProcessRecord,则需要杀死该进程并退出
if (app == null) {
...
return false;
}
// If this application record is still attached to a previous
// process, clean it up now.
if (app.thread != null) {
//如果从ProcessRecord中获取的IApplicationThread不为空,则需要处理该IApplicationThread
//因为有可能此Pid为复用,旧应用进程刚释放,内部IApplicationThread尚未清空,
//同时新进程又刚好使用了此Pid
handleAppDiedLocked(app, true, true);
}
//创建死亡代理(进程kill后通知AMS)
AppDeathRecipient adr = new AppDeathRecipient(app, pid, thread);
//进程注册成功,移除超时通知
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
...
try {
//绑定Application
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked());
updateLruProcessLocked(app, false, null);
} catch (Exception e) {
...
//bindApplication失败后,重启进程
startProcessLocked(app, "bind fail", processName);
return false;
}
try {
//启动Activity(启动淘宝MainActivity)
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;//didSomething表示是否有启动四大组件
}
} catch (Exception e) {
badApp = true;
}
...
//绑定service和Broadcast的Application
if (badApp) {
//如果以上组件启动出错,则需要杀死进程并移除记录
app.kill("error during init", true);
handleAppDiedLocked(app, false, true);
return false;
}
//如果以上没有启动任何组件,那么didSomething为false
if (!didSomething) {
//调整进程的oom_adj值, oom_adj相当于一种优先级
//如果应用进程没有运行任何组件,那么当内存出现不足时,该进程是最先被系统“杀死”
updateOomAdjLocked();
}
return true;
}
在attachApplicationLocked
中有两个比较重要的方法函数:
-
thread.bindApplication(…)
: 绑定Application到ActivityThread -
mStackSupervisor.attachApplicationLocked(app
) : 启动Activity(Android 7.0前为mMainStack.realStartActivityLocked()
)
ApplicationThread.bindApplication绑定Application到ActivityThread
在上面我们说道,ActivityThread
通过ApplicationThread
与AMS进行通讯,所以上面的thread.bindApplication(...)
方法,就应该是通过ApplicationThread
进行传达。
在ActivityThread
的内部类ApplicationThread
中,我们找到bindApplication
方法
//ActivityThread
//内部类ApplicationThread
private class ApplicationThread extends ApplicationThreadNative {
public final void bindApplication(...一大堆参数...) {
AppBindData data = new AppBindData();
//给data设置参数...
...
sendMessage(H.BIND_APPLICATION, data);
}
}
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
Message msg = Message.obtain();
//给msg设置参数
...
mH.sendMessage(msg);
}
发送消息是通过H
的Handler
类来完成的。
private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
public static final int PAUSE_ACTIVITY = 101;
...
public static final int RESUME_ACTIVITY = 107;
public static final int DESTROY_ACTIVITY = 109;
public static final int BIND_APPLICATION = 110;
public static final int EXIT_APPLICATION = 111;
...
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.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
...
//绑定application
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
}
}
}
可以看出,这个H
类相当于ActivityThread
和ApplicationThread
的中介人,也就是拉皮条的。
ActivityThread
通过ApplicationThread
与AMS通讯。
ApplicationThread
通过H
与ActivityThread
通讯,处理Activity事务。
那么既然H
、ApplicationThread
都在ActivityThread
类里,为何ApplicationThread
还要通过Handler
来发送消息?
- 便于集中管理,方便打印Log日志等,
H
就是这其中的大管家。 -
ActivityThread
通过ApplicationThread
和AMS进行进程间通信,AMS以进程通讯的方式来完成ActivityThread
的请求后调用ApplicationThread
中的Binder方法,然后ApplicationThread
会向H
发送消息,H
收到消息后会将ApplicationThread
中的逻辑切换到ActivityThread
中去执行,即切换到主线程中去执行,这个过程就是主线程的消息循环模型。
而且有一点要注意的是,这个ActivityThread
并不是一个线程Thread,它是final类并且无继承或者实现其它类,它的作用就是在main
方法内消息循环,处理主线程事务。(还需了解Looper及消息机制)
言归正传,上面ApplicationThread
给H
发送BIND_APPLICATION
标识,在H
中,通过handleBindApplication
处理Application的绑定事务。
//ActivityThread
private void handleBindApplication(AppBindData data) {
...
//根据传递过来的ApplicationInfo创建一个对应的LoadedApk对象
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);//获取LoadedApk
//禁止在主线程使用网络操作
if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) {
StrictMode.enableDeathOnNetwork();
}
//7.0引入Fileprovide
if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
StrictMode.enableDeathOnFileUriExposure();
}
...
//创建进程对应的Android运行环境ContextImpl
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
if ((InstrumentationInfo)ii != null) {
...
} else {
//注意Activity的所有生命周期方法都会被Instrumentation对象所监控,
//也就说执行Activity的生命周期方法前后一定会调用Instrumentation对象的相关方法
mInstrumentation = new Instrumentation();
}
try {
...
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
//加载进程对应Package中携带的ContentProvider
installContentProviders(app, data.providers);
...
mInstrumentation.onCreate(data.instrumentationArgs);
try {
//这里会调用Application的onCreate方法
//故此Applcation对象的onCreate方法会比ActivityThread的main方法后调用
//但是会比这个应用的所有activity先调用
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
...
}
} finally {
StrictMode.setThreadPolicy(savedPolicy);
}
}
如上文所述,handleBindApplication
的目的是让一个Java进程融入到Android体系中。
因此,该函数中的代码主要进行以下工作:
- 按照Android的要求,完成对进程基本参数的设置置,包括设置进程名、时区、资源及兼容性配置;
同时也添加了一些限制,例如主线程不能访问网络等。 - 创建进程对应的ContextImpl、LoadedApk、Application等对象,同时加载Application中的ContentProvider,并初始化Application。
- 使用
Instrumentation
监控Activity的生命周期。(一个进程对应一个Instrumentation
实例)
当完成上述工作后,新建的进程终于加入到了Android体系。
AMS通知淘宝绑定Application并启动MainActivity。
ActivityStackSupervisor.attachApplicationLocked启动Activity
在上述代码AMS的attachApplicationLocked
方法中,我们说道:
在
attachApplicationLocked
中有两个比较重要的方法函数,分析到这里我们的文章也要进入尾声了。
- thread.bindApplication(…) : 绑定Application到ActivityThread
- mStackSupervisor.attachApplicationLocked(app) : 启动Activity
绑定了Application之后,我们就可以启动Activity(淘宝MainActivity)。
//ActivityStackSupervisor
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
final String processName = app.processName;
boolean didSomething = false;
//ActivityStackSupervisor维护着终端中所有ActivityStack
//此处通过轮询,找出前台栈顶端的待启动Activity
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (!isFocusedStack(stack)) {
continue;
}
ActivityRecord hr = stack.topRunningActivityLocked();
if (hr != null) {
//前台待启动的Activity与当前新建的进程一致时,启动这个Activity
if (hr.app == null && app.uid == hr.info.applicationInfo.uid && processName.equals(hr.processName)) {
try {
//realStartActivityLocked进行实际的启动工作
if (realStartActivityLocked(hr, app, true, true)) {
didSomething = true;
}
} catch (RemoteException e) {
}
}
}
}
}
return didSomething;
}
大概系统工程师也觉得这个启动过程贼鸡儿绕了,最终启动的方法命名为realStartActivityLocked
,意味着告诉你,大伙儿不要搞晕了,这个就是最后启动Activity的方法了。realStartActivityLocked()方法
通过ApplicaitonThread的scheduleLaunchActivity()
调用客户端Binder实体的方法,最后我们直捣黄龙,在ActivityStackSupervisor
方法中,我们找到如下代码
//ActivityStackSupervisor
//通过ApplicaitonThread调用客户端Binder实体的方法。
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
public final void scheduleResumeActivity(IBinder token, int processState,
boolean isForward, Bundle resumeArgs) {
updateProcessState(processState, false);
sendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0);
}
看到这里想必大伙儿都明白了,AMS最后通过ApplicationThread
通知ActivityThread
启动Activity
,感觉这一切的通讯都像发电报一样,鬼斧神工出神入化,皆出架构师之目营心匠。
那么到这里我们就能推算出接下来的老套路了
ApplicationThread—> H—> ActivityThread—> 最终启动Activity的方法。
ActivityThread
//ActivityThread
//内部类ApplicationThread
private class ApplicationThread extends ApplicationThreadNative {
@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
CompatibilityInfo compatInfo, String referrer,
IVoiceInteractor voiceInteractor,
int procState, Bundle state, PersistableBundle persistentState,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
//设置参数
...
//从LAUNCH_ACTIVITY这个标识我们就可以知道,它就是用来启动Activity
sendMessage(H.LAUNCH_ACTIVITY, r);
}
}
private class H extends Handler {
...
//用Handler发送了一个Message。Handler的处理会最终调用handlerLaunchActivity方法
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;
//利用ApplicationInfo等信息得到对应的LoadedApk,保存到ActivityClientRecord
//ActivityClientRecord包含Activity相关的信息
r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
...
}
}
}
}
//ActivityThread
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
...
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
...
}
...
}
handleLaunchActivity
方法里有有两个重要的函数调用:
- performLaunchActivity : 会调用Activity的onCreate、onStart、onResotreInstanceState方法
- handleResumeActivity : 会调用Activity的onResume方法
从上面的源码可以看出,
performLaunchActivity
方法最终完成了Activity对象的创建和启动过程,并且ActivityThread通过handleResumeActivity
方法来调用被启动Activity的onResume这一生命周期方法。
performLaunchActivity
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);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
...
}
3、通过LoadedApk的makeApplication
方法来创建Application对象。
//ActivityThread的performLaunchActivity方法
Application app = r.packageInfo.makeApplication(false, mInstrumentation);//r.packageInfo为LoadedApk对象
其实在我们上面的bindApplication中,我们就有介绍到通过LoadedApk
创建Application,并且创建完毕后,通过Instrumentation
的callApplicationOnCreate
来调用Application的onCreate
方法
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
...
mInstrumentation.callApplicationOnCreate(app);
所以第三步是为了判断Application是否为空,而且我们从makeApplication
方法中也能看出如果Application已经被创建过了,那么就不会再重复创建了。
4、创建ContextImpl对象,并通过Activity的attach方法来完成一些重要数据的初始化。
Context appContext = createBaseContextForActivity(r, activity);//创建ContextImpl对象
Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
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);
ContextImpl是一个很重要的数据结构,它是Context的具体实现,Context中的大部分逻辑都是由ContextImpl来完成的。ContextImpl来完成的。ContextImpl是通过Activity的attach方法来和Activity建立关联的,除此之外,在attach方法中Activity还会完成Window的创建并建立自己和Window的关联,这样当Window接收到外部输入事件后就可以将事件传递给Activity。
5、调用Activity的onCreate方法
mInstrumentation.callActivityOnCreate(activity, r.state);
由于Activity的onCreate已经被调用,这也意味着Activity已经完成了整个启动过程。
6、调用Activity的onStart、onResotreInstanceState方法
mInstrumentation.callActivityOnCreate(activity, r.state);
...
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
activity.performCreate(icicle);
postPerformCreate(activity);
}
对activity.performCreate(icicle);
这一行代码熟悉吗?这一行里面就调用了传说中的Activity的入口函数onCreate()
,不信?接着往下看Activity.performCreate()
final void performCreate(Bundle icicle) {
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
没骗你吧,onCreate在这里调用了吧。
参考文章
【凯子哥带你学Framework】Activity启动过程全解析