Android Activity启动过程全解析
2015-11-25 10:15
459 查看
首先参考:
【凯子哥带你学Framework】Activity启动过程全解析
每一个App其实都是
一个单独的dalvik虚拟机
一个单独的进程
Android是基于Linux System的,当你的手机开机的时候,Linux的内核加载完成之后就会启动一个叫“init“的进程。zygote进程是由init进程fork出来的,当系统里面的第一个zygote进程运行之后,在这之后再开启App,就相当于开启一个新的进程。而为了实现资源共用和更快的启动速度,Android系统开启新进程的方式,是通过fork第一个zygote进程实现的.
Android Framework里面两大非常重要的进程之一
1. zygote进程
2. SystemServer也是一个进程,而且是由zygote进程fork出来的,这个主要开启重要的系统服务,比如ActivityManagerService、PackageManagerService、WindowManagerService
ActivityManagerService进行初始化的时机很明确,就是在SystemServer进程开启的时候,就会初始化ActivityManagerService
在创建AMS之前会调用createSystemContext()创建系统上下文的时候,也已经完成了mSystemContext和ActivityThread的创建。然后创建AMS,在然后,会开启系统的Launcher程序,完成系统界面的加载与显示。
如果想打开一个App的话,需要AMS去通知zygote进程,来fork一个新进程,来开启我们的目标App的。除此之外,其实所有的Activity的开启、暂停、关闭都需要AMS来控制,所以我们说,AMS负责系统中所有Activity的生命周期。
我们的App和AMS(SystemServer进程)还有zygote进程分属于三个独立的进程,他们之间如何通信呢?
App与AMS通过Binder机制进行IPC通信,AMS(SystemServer进程)与zygote通过Socket进行IPC通信。
Launcher中点击图标,Launcher会判断哪个图标对应哪个应用程序,封装intent,然后使用这个intent开启一个App,其实和我们在Activity中直接startActivity()基本一样,都是调用了Activity.startActivityForResult()。
先提一下,当AMS通知ActivityThread启动一个activity的时候,首先会执行handleLaunchActivity方法,这个方法里面会去回调activity的各个生命周期函数。具体handleLaunchActivity方法在什么时候被调用后面分析
performLaunchActivity方法创建activity,内部其实都是调用Instrumentation的相关方法,然后在调用activity的onCreat和onStart等生命周期方法
这里举个例子,执行了mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);怎么就回调了activity的onCreate方法
performLaunchActivity执行完后执行handleResumeActivity-performResumeActivity方法,有r.activity.performResume();
然后就回调了activity的onResume方法
这里稍微总结一下:
第一步,执行activity有构造函数,那么这个构造函数是优先于onCreate方法执行的
第二步,performLaunchActivity中把一个ContextImpl对象给该Activity的父类ContextWrapper的mBase属性,这里的分析见《Android Context详解》
第二步,performLaunchActivity中调用attach方法,赋值mWindow,mApplication,mWindowManager等。mWindow,mWindowManager有啥用?见《Android 窗口添加机制系列1-Activity》
第二步,performLaunchActivity中然后回调activity的onCreate,onStart,onRestoreInstanceState,onPostCreate方法
第三步,第二部创建完初始化完acitivity调用handleResumeActivity回调activity的onResume方法,在窗口机制里面,也说过这里会把顶层的DecorView添加到window-WMS中去
ActivityManagerProxy.startActivity(),在这里面做的事情就是IPC通信,利用Binder对象,调用transact(),把所有需要的参数封装成Parcel对象,向AMS发送数据进行通信。
看这里IBinder b = ServiceManager.getService(“activity”);之前有介绍过获取PhoneInterfaceManager的时候是这样的ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE)); 这个类似,所以其实这里的IBinder拿到的其实就是AMS(ActivityManagerService)
客户端:ActivityManagerProxy =====>Binder驱动=====> ActivityManagerService:服务器
流程现在进入了AMS,告诉AMS我要启动一个activity了,接下来AMS中的流程就不贴了,也没啥必要,看参考链接的吧。
【凯子哥带你学Framework】Activity启动过程全解析
ActivityStack的resumeTopActivityInnerLocked方法中
说明在启动activity前,栈顶的activity需要先onpause,新的activity才能启动,所以不能在onpause中做耗时的操作,否则会造成新的activity启动的很慢,此时可以把耗时操作放在Onstop中处理
然后AMS通过以下方式来通知ActivityThread
客户端:ApplicationThread <=====Binder驱动<===== ApplicationThreadProxy:服务器
来一张高清无码大图,方便大家记忆:
如果应用进程还没打开,那么首先会开启main线程,当然就是执行ActivityThread的main方法
这里做了两件事情
开启主线程的消息循环
做主线程的attach
attach方法里执行mgr.attachApplication(mAppThread),然后通过Binder调用到AMS里面对应的attachApplication方法
AMS方法attachApplicationLocked
首先thread.bindApplication中
thread是IApplicationThread,实际上就是ApplicationThread在服务端的代理类ApplicationThreadProxy,然后又通过IPC就会调用到ApplicationThread的对应方法
先调用ApplicationThreadProxy的bindApplication方法,然后通过IBinder调用的是ApplicationThread的bindApplication方法中会sendMessage(),里面有函数的编号H.BIND_APPLICATION,然后这个Messge会被H这个Handler处理
ApplicationThread是ActivityThread的内部类
上面的代码也充分说明了AMS通过以下方式来通知ActivityThread
客户端:ApplicationThread <=====Binder驱动<===== ApplicationThreadProxy:服务器
看到了吗? 重要执行到了handleBindApplication,这个方法是不是很熟悉?之前在《Android Context详解》这篇文章就说到,创建单例的Application对像就是从这个方法开始滴。
然后执行完thread.bindApplication也就是说此时完成了Application相关的初始化,然后执行mStackSupervisor.attachApplicationLocked(app);然后会调用realStartActivityLocked方法。
realStartActivityLocked方法里有这么一行
跟上面的是不是很像,先调用ApplicationThreadProxy的scheduleLaunchActivity方法,然后通过IBinder调用的是ApplicationThread的scheduleLaunchActivity方法。scheduleLaunchActivity方法中
同上发送一个标识为H.LAUNCH_ACTIVITY的消息
最后看到了吗?执行了handleLaunchActivity方法,这个方法很熟悉吧?执行Activity生命周期就是从这个方法开始的,见《Instrumentation》章节
现在整个流程终于清晰了吧?
另一方面,如果是启动同一个应用的activity,那么就不会有bindApplication的流程啦,就不会再重复初始化application,只会初始化该activity
【凯子哥带你学Framework】Activity启动过程全解析
关键概念
zygote进程
这里面讲的很详细,先摘抄其中重要的部分出来,方便以后记忆每一个App其实都是
一个单独的dalvik虚拟机
一个单独的进程
Android是基于Linux System的,当你的手机开机的时候,Linux的内核加载完成之后就会启动一个叫“init“的进程。zygote进程是由init进程fork出来的,当系统里面的第一个zygote进程运行之后,在这之后再开启App,就相当于开启一个新的进程。而为了实现资源共用和更快的启动速度,Android系统开启新进程的方式,是通过fork第一个zygote进程实现的.
Android Framework里面两大非常重要的进程之一
1. zygote进程
2. SystemServer也是一个进程,而且是由zygote进程fork出来的,这个主要开启重要的系统服务,比如ActivityManagerService、PackageManagerService、WindowManagerService
AMS
ActivityManagerService,简称AMS,服务端对象,负责系统中所有Activity的生命周期。ActivityManagerService进行初始化的时机很明确,就是在SystemServer进程开启的时候,就会初始化ActivityManagerService
在创建AMS之前会调用createSystemContext()创建系统上下文的时候,也已经完成了mSystemContext和ActivityThread的创建。然后创建AMS,在然后,会开启系统的Launcher程序,完成系统界面的加载与显示。
如果想打开一个App的话,需要AMS去通知zygote进程,来fork一个新进程,来开启我们的目标App的。除此之外,其实所有的Activity的开启、暂停、关闭都需要AMS来控制,所以我们说,AMS负责系统中所有Activity的生命周期。
我们的App和AMS(SystemServer进程)还有zygote进程分属于三个独立的进程,他们之间如何通信呢?
App与AMS通过Binder机制进行IPC通信,AMS(SystemServer进程)与zygote通过Socket进行IPC通信。
Launcher
当我们点击手机桌面上的图标的时候,App就由Launcher开始启动了。Launcher本质上也是一个应用程序,和我们的App一样。Launcher中点击图标,Launcher会判断哪个图标对应哪个应用程序,封装intent,然后使用这个intent开启一个App,其实和我们在Activity中直接startActivity()基本一样,都是调用了Activity.startActivityForResult()。
Instrumentation
每个Activity都持有Instrumentation对象的一个引用,但是整个进程只会存在一个Instrumentation对象。当startActivityForResult()调用之后,实际上还是调用了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; }
先提一下,当AMS通知ActivityThread启动一个activity的时候,首先会执行handleLaunchActivity方法,这个方法里面会去回调activity的各个生命周期函数。具体handleLaunchActivity方法在什么时候被调用后面分析
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) { .......... 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,内部其实都是调用Instrumentation的相关方法,然后在调用activity的onCreat和onStart等生命周期方法
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { Activity activity = null; try { java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); //说明如果一个activity有构造函数,那么这个构造函数是优先于onCreate方法执行的 activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); } try { //把之前创建的application对象取出来 Application app = r.packageInfo.makeApplication(false, mInstrumentation); if (activity != null) { //绑定ContextImpl对象给该Activity Context appContext = createBaseContextForActivity(r, activity); //做attach,attah里面会赋值mWindow,mApplication,mWindowManager等 activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config, r.voiceInteractor); activity.mCalled = false; if (r.isPersistable()) { //最终会调用到Activity的onCreate方法 mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); } else { mInstrumentation.callActivityOnCreate(activity, r.state); } if (!r.activity.mFinished) { //实际调用mInstrumentation.callActivityOnStart(this);,然后调用Activity的onStart方法 activity.performStart(); r.stopped = false; } if (!r.activity.mFinished) { if (r.isPersistable()) { if (r.state != null || r.persistentState != null) { //调用Activity的onRestoreInstanceState方法 mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state, r.persistentState); } } else if (r.state != null) { mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state); } } if (!r.activity.mFinished) { activity.mCalled = false; if (r.isPersistable()) { ////调用Activity的onPostCreate方法 mInstrumentation.callActivityOnPostCreate(activity, r.state, r.persistentState); } else { mInstrumentation.callActivityOnPostCreate(activity, r.state); } } } } return activity; }
这里举个例子,执行了mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);怎么就回调了activity的onCreate方法
//Instrumentation方法 public void callActivityOnCreate(Activity activity, Bundle icicle) { prePerformCreate(activity); activity.performCreate(icicle); postPerformCreate(activity); } //Activity方法 final void performCreate(Bundle icicle, PersistableBundle persistentState) { onCreate(icicle, persistentState); mActivityTransitionState.readState(icicle); performCreateCommon(); }
performLaunchActivity执行完后执行handleResumeActivity-performResumeActivity方法,有r.activity.performResume();
final void performResume() { ............ mInstrumentation.callActivityOnResume(this); ............ }
然后就回调了activity的onResume方法
这里稍微总结一下:
第一步,执行activity有构造函数,那么这个构造函数是优先于onCreate方法执行的
第二步,performLaunchActivity中把一个ContextImpl对象给该Activity的父类ContextWrapper的mBase属性,这里的分析见《Android Context详解》
第二步,performLaunchActivity中调用attach方法,赋值mWindow,mApplication,mWindowManager等。mWindow,mWindowManager有啥用?见《Android 窗口添加机制系列1-Activity》
第二步,performLaunchActivity中然后回调activity的onCreate,onStart,onRestoreInstanceState,onPostCreate方法
第三步,第二部创建完初始化完acitivity调用handleResumeActivity回调activity的onResume方法,在窗口机制里面,也说过这里会把顶层的DecorView添加到window-WMS中去
Activity启动流程
前面说过startActivity实际上调用的是Instrumentation的execStartActivity方法public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Fragment target, Intent intent, int requestCode, Bundle options) { IApplicationThread whoThread = (IApplicationThread) contextThread; if (mActivityMonitors != null) { synchronized (mSync) { final int N = mActivityMonitors.size(); for (int i=0; i<N; i++) { final ActivityMonitor am = mActivityMonitors.get(i); if (am.match(who, null, intent)) { am.mHits++; if (am.isBlocking()) { return requestCode >= 0 ? am.getResult() : null; } break; } } } } try { intent.migrateExtraStreamToClipData(); intent.prepareToLeaveProcess(); int result = ActivityManagerNative.getDefault() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mWho : null, requestCode, 0, null, options); checkStartActivityResult(result, intent); } catch (RemoteException e) { } return null; } 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"); if (false) { Log.v("ActivityManager", "default service binder = " + b); } IActivityManager am = asInterface(b); if (false) { Log.v("ActivityManager", "default service = " + am); } 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); } }
ActivityManagerProxy.startActivity(),在这里面做的事情就是IPC通信,利用Binder对象,调用transact(),把所有需要的参数封装成Parcel对象,向AMS发送数据进行通信。
看这里IBinder b = ServiceManager.getService(“activity”);之前有介绍过获取PhoneInterfaceManager的时候是这样的ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE)); 这个类似,所以其实这里的IBinder拿到的其实就是AMS(ActivityManagerService)
public static final String ACTIVITY_SERVICE = "activity"; public void setSystemProcess() { try { ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true); } 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.writeInt(requestCode); data.writeInt(startFlags); ........ mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0); ........ return result; }
客户端:ActivityManagerProxy =====>Binder驱动=====> ActivityManagerService:服务器
流程现在进入了AMS,告诉AMS我要启动一个activity了,接下来AMS中的流程就不贴了,也没啥必要,看参考链接的吧。
【凯子哥带你学Framework】Activity启动过程全解析
//省略AMS中的代码流程
ActivityStack的resumeTopActivityInnerLocked方法中
// We need to start pausing the current activity so the top one // can be resumed... boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0; boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause); if (mResumedActivity != null) { pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause); if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Pausing " + mResumedActivity); }
说明在启动activity前,栈顶的activity需要先onpause,新的activity才能启动,所以不能在onpause中做耗时的操作,否则会造成新的activity启动的很慢,此时可以把耗时操作放在Onstop中处理
然后AMS通过以下方式来通知ActivityThread
客户端:ApplicationThread <=====Binder驱动<===== ApplicationThreadProxy:服务器
来一张高清无码大图,方便大家记忆:
如果应用进程还没打开,那么首先会开启main线程,当然就是执行ActivityThread的main方法
public static void main(String[] args) { Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } AsyncTask.init(); if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); } }
这里做了两件事情
开启主线程的消息循环
做主线程的attach
attach方法里执行mgr.attachApplication(mAppThread),然后通过Binder调用到AMS里面对应的attachApplication方法
AMS方法attachApplicationLocked
private final boolean attachApplicationLocked(IApplicationThread thread, int pid) { ........... thread.bindApplication(processName, appInfo, providers, app.instrumentationClass, profilerInfo, app.instrumentationArguments, app.instrumentationWatcher, app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace, isRestrictedBackupMode || !normalMode, app.persistent, new Configuration(mConfiguration), app.compat, getCommonServicesLocked(), mCoreSettingsObserver.getCoreSettingsLocked()); ........... mStackSupervisor.attachApplicationLocked(app); ...........
首先thread.bindApplication中
thread是IApplicationThread,实际上就是ApplicationThread在服务端的代理类ApplicationThreadProxy,然后又通过IPC就会调用到ApplicationThread的对应方法
先调用ApplicationThreadProxy的bindApplication方法,然后通过IBinder调用的是ApplicationThread的bindApplication方法中会sendMessage(),里面有函数的编号H.BIND_APPLICATION,然后这个Messge会被H这个Handler处理
private class H extends Handler { ...ignore some code... public static final int BIND_APPLICATION = 110; ...ignore some code... public void handleMessage(Message msg) { switch (msg.what) { ...ignore some code... 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; ...ignore some code... } }
ApplicationThread是ActivityThread的内部类
上面的代码也充分说明了AMS通过以下方式来通知ActivityThread
客户端:ApplicationThread <=====Binder驱动<===== ApplicationThreadProxy:服务器
看到了吗? 重要执行到了handleBindApplication,这个方法是不是很熟悉?之前在《Android Context详解》这篇文章就说到,创建单例的Application对像就是从这个方法开始滴。
然后执行完thread.bindApplication也就是说此时完成了Application相关的初始化,然后执行mStackSupervisor.attachApplicationLocked(app);然后会调用realStartActivityLocked方法。
realStartActivityLocked方法里有这么一行
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration), r.compat, r.task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results, newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
跟上面的是不是很像,先调用ApplicationThreadProxy的scheduleLaunchActivity方法,然后通过IBinder调用的是ApplicationThread的scheduleLaunchActivity方法。scheduleLaunchActivity方法中
同上发送一个标识为H.LAUNCH_ACTIVITY的消息
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);
最后看到了吗?执行了handleLaunchActivity方法,这个方法很熟悉吧?执行Activity生命周期就是从这个方法开始的,见《Instrumentation》章节
现在整个流程终于清晰了吧?
另一方面,如果是启动同一个应用的activity,那么就不会有bindApplication的流程啦,就不会再重复初始化application,只会初始化该activity
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories