四大组件的运行状态:
Android中的四大组件中除了BroadcastReceiver以外,其他三种组件都必须在Android Mainfrst中注册。对于,BroadcastReceiver来说,他既可以在AndroidMainfrst中注册也可以通过代码来注册。在调用方式上,Activity,Service和BroadcastReceiver需要借助Intent,而ContentProvider则无需借助Intent。
Activity的工作过程:
为了方便日常的开发工作,系统对四大组件的工作过程进行了很大程度的封装,这使得开发者无需关注实现细节即可快速的使用四大组件。Activity作为很重要的一个组件,其内部工作过程系统当然也是做了很多的封装,这种封装使得启动一个Activity变得异常的简单。在显示调用的情形下,只需要通过如下代码即可完成:
Intent intent=new Intent(this,TestActivity.class); startActivity(intent);
通过上面的代码即可启动一个具体的activity,然后新Activity就会被系统启动并展示在 用户的眼前,这个过程对于Android开发者来说最普通不过了,这也是很理所当然的事情,但是有没有想过系统内部到底是如何启动一个Activity的呢?下面我们就来介绍一下。
注意一点:在研究内部实现上应该更加侧重于对整体流程的把握,而不能深入代码细节不能自拔,太深入代码细节往往会导致越看越迷茫的撞到。无法对整体流程建立足够的认识,取而代之的是繁琐的细节。但是代码的细节本身不具有太多的指导意义,因此这种学习状态是要极力避免的。所以本博客会侧重于对Activity工作过程的分析整体流程。
我们从Acitivity的startActivity的方法开始分析,startActivity的方法有好几种重载方式,但是他们最终都会调用startActivityForResult方法,实现如下:
public void startActivityForResult(Intent intent, int requestCode, 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; } } 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这部分逻辑,mParent代表的是ActivityGroup,ActivityGroup最开始被用来在一个界面中嵌入多个子Activity,但是其在API13中已经被废弃了,系统推荐采用Fragment来代替ActivityGroup,Fragment的好处就不多说了、在上面的代码中需要注意mMainThread.getApplicationThread()这个参数,他的类型是ApplicationThread,ApplicationThread是ActivityThread在Activity的启动过程中发挥着很重要的作用。接着看一下Instrumentation的execStartActiivty方法。如下所示:
public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity 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.mEmbeddedID : null, requestCode, 0, null, null, options); checkStartActivityResult(result, intent); } catch (RemoteException e) { } return null; }
从上面的代码来看,启动Actiivty真正的实现由ActivityManagerNative.getDefault()的startActivity方法完成。ActivityManagerService(简称AMS)继承自Binder并实现了IActivityManager这个Binder接口,因此AMS也是一个Binder,他是IActivityManager的具体实现。由于ActivityManagerNative.getDefault()其实是一个IActivityManager类型的Binder对象,因此他的具体实现是AMS。可以发现,在ActivityManagerNative中。AMS这个Binder对象采用单例模式对外提供,Singleton是一个单利的封装类,第一次调用它的get方法时他会通过create方法来初始化AMS这个Binder对象,在后续的调用中则直接返回之前创建的对象,源码如下:
static public IActivityManager More ...getDefault() { return gDefault.get(); }
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() { protected IActivityManager More ...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的完整源码地址:源码,有兴趣的可以去阅读一下。
从上面的分析可以知道,Activity由ActivityManagerNative.getDefault()来启动。而ActivityManagerNative.getDefault()实际上是AMS,因此Activity的启动过程又转移到了AMS中,为了继续分析这个过程,只需要查看AMS的startActivity方法即可,在分析AMS的startActivity方法之前,我们先回过头来看一下Instrumentation的execStartActivity方法,其中有一行代码:checkStartActivityResult(result,intent),直观上看起来这个方法的作用像是在检查启动Activity的记过,他的具体实现如下所示:
/*package*/ static void checkStartActivityResult(int res, Object intent) { if (res >= ActivityManager.START_SUCCESS) { return; } switch (res) { case ActivityManager.START_INTENT_NOT_RESOLVED: case ActivityManager.START_CLASS_NOT_FOUND: if (intent instanceof Intent && ((Intent)intent).getComponent() != null) throw new ActivityNotFoundException( "Unable to find explicit activity class " + ((Intent)intent).getComponent().toShortString() + "; have you declared this activity in your AndroidManifest.xml?"); throw new ActivityNotFoundException( "No Activity found to handle " + intent); case ActivityManager.START_PERMISSION_DENIED: throw new SecurityException("Not allowed to start activity " + intent); case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT: throw new AndroidRuntimeException( "FORWARD_RESULT_FLAG used while also requesting a result"); case ActivityManager.START_NOT_ACTIVITY: throw new IllegalArgumentException( "PendingIntent is not an activity"); default: throw new AndroidRuntimeException("Unknown error code " + res + " when starting " + intent); } }
从上面的代码可以看出,checkStartActivityResult的作用很明显,就是检查启动Activity的结果,当无法正确启动一个Activity时,这个方法会抛出异常信息,其中最熟悉不过的就是"unable to find expliit activity class; have you declared this activity in your androidmainfest.xml"这个异常我就不说了,你懂的。
接着我们继续分析AMS的startActivity方法,如下所示:
public final int More ...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()); }
public final int More ...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) { enforceNotIsolatedCaller("startActivity"); userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, false, true, "startActivity", null); return mMainStack.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profileFile, profileFd, null, null, options, userId); }
可以看出,Activity的启动过程又转移到了ActivityStackSupervisor的startActivityMayWait方法中了。在startActivityMayWait中又调用了startActivityLocked方法,接着startActivityLocked又调用了ActivityStack的resumeTopActivityiesLocked方法,这个时候启动过程已经从ActivityStackSupervisor转移到了ActivityStack。
ActivityStack的resumeTopActivitiesLocked方法的实现如下所示:
final boolean More ...resumeTopActivityLocked(ActivityRecord prev, Bundle options) { if (inResumeTopActivity) { // Don't even start recursing. return false; } boolean result = false; try { // Protect against recursion. inResumeTopActivity = true; result = resumeTopActivityInnerLocked(prev, options); } finally { inResumeTopActivity = false; } return result; }
从上面的代码可以看出,resumeTopActivityLocked调用了resumeTopActivityInnerLocked方法,resumeTopActivityInnerLocked方法又调用了ActivityStackSupervisor的satrtSpecificActivityLocked方法,satrtSpecificActivityLocked的源码如下:
void More ...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); r.task.stack.setLaunchTime(r); if (app != null && app.thread != null) { try { if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0 || !"android".equals(r.info.packageName)) { // Don't add this if it is a platform component that is marked // to run in multiple processes, because this is actually // part of the framework so doesn't make sense to track as a // separate apk in the process. app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode, mService.mProcessStats); } realStartActivityLocked(r, app, andResume, checkConfig); return; } catch (RemoteException e) { Slog.w(TAG, "Exception when starting activity " + r.intent.getComponent().flattenToShortString(), e); } // If a dead object exception was thrown -- fall through to // restart the application. } mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, "activity", r.intent.getComponent(), false, false, true); }
从上面的代码可以看出,satrtSpecificActivityLocked方法调用了realStartActivityLocked方法,为了更清晰的说明Activity的启动过程在ActivityStatckSupervisor和ActivityStack之间的传递顺序,下面给出一张流程图。
在ActivityStackSupervisor的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);
这段代码很重要,其中app.thread的类型为IApplicationThread,IApplicationThread的声明如下:
因为他继承了IInterface接口,所以他是一个Binder类型的接口,从IApplicationThread声明的接口方法中可以看出,其内部包含了大量启动,停止Activity 的接口,此外还包含了启动和停止服务的接口,从接口的方法的命名可以猜测,IApplicationThread这个Binder接口的实现者完成了大量和Activity以及Service启动停止相关的功能。
那么IApplicationThread的实现者到底是什么?答案就是ActivityThread中的内部类ApplicationThread,洗面来看ApplicationThread的定义:
private class More ...ApplicationThread extends ApplicationThreadNative public abstract class More ...ApplicationThreadNative extends Binder implements IApplicationThread
可以看出,ApplicationThread继承了ApplicationThreadNative,而ApplicationThreadNative则继承了Binder并实现了IApplicationThread接口。如果读者还记得系统的AIDL文件自动生成的代码,就会发现ApplicationThreadNative的作用其实和系统为AIDL文件生成的类是一样的。
在ApplicationThreadNative的内部,还有一个ApplicationThreadProxy类,这个类的实现如下所示,其实这个内部类也是系统为AIDL文件自动生成的代理类。所以ApplicationThreadNative就是IApplicationThread的实现者,由于ApplicationThreadNative被系统定义为抽象类,所以ApplicationThread就成了IApplicationThread的最终实现者了。
class More ...ApplicationThreadProxy implements IApplicationThread { private final IBinder mRemote; public More ...ApplicationThreadProxy(IBinder remote) { mRemote = remote; } public final IBinder More ...asBinder() { return mRemote; } public final void More ...schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges, boolean dontReport) 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); data.writeInt(dontReport ? 1 : 0); mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); data.recycle(); } public final void More ...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(); } ... }
绕了一大圈,Activity的启动过程最终回到了ApplicationThread中,ApplicationThread通过scheduleLaunchActivity方法来启动Activity,代码如下:
public final void More ...scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo, IVoiceInteractor voiceInteractor, int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) { updateProcessState(procState, false); ActivityClientRecord r = new ActivityClientRecord(); r.token = token; r.ident = ident; r.intent = intent; r.voiceInteractor = voiceInteractor; r.activityInfo = info; r.compatInfo = compatInfo; r.state = state; r.persistentState = persistentState; r.pendingResults = pendingResults; r.pendingIntents = pendingNewIntents; r.startsNotResumed = notResumed; r.isForward = isForward; r.profilerInfo = profilerInfo; updatePendingConfiguration(curConfig); sendMessage(H.LAUNCH_ACTIVITY, r); }
接下来看一下Handler H对消息的处理,如下所示:
private class More ...H extends Handler { 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 More ...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"); final 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&1) != 0, msg.arg2, (msg.arg1&2) != 0); maybeSnapshot(); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break;
....
}
<span style="font-family: monospace;font-size:14px; white-space: pre;"> </span><span class="kw" style="color: rgb(127, 0, 85); font-weight: bold; font-family: monospace;font-size:14px; white-space: pre;">if</span><span style="font-family: monospace;font-size:14px; white-space: pre;"> (</span><span class="mark-5#1" style="font-family: monospace;font-size:14px; white-space: pre;"><a target=_blank href="http://grepcode.com/file/repo1.maven.org/maven2/org.robolectric/android-all/5.0.0_r2-robolectric-0/android/app/ActivityThread.java#ActivityThread.0DEBUG_MESSAGES" title="boolean DEBUG_MESSAGES" class="hidden" style="padding: 0px; margin: 0px; color: rgb(0, 0, 0); text-decoration: none;">DEBUG_MESSAGES</a></span><span style="font-family: monospace;font-size:14px; white-space: pre;">) Slog.</span><a target=_blank href="http://grepcode.com/file/repo1.maven.org/maven2/org.robolectric/android-all/5.0.0_r2-robolectric-0/android/util/Slog.java#Slog.v%28java.lang.String%2Cjava.lang.String%29" title="android.util.Slog.v(java.lang.String,java.lang.String) : int" style="padding: 0px; margin: 0px; color: rgb(51, 102, 187); font-family: monospace;font-size:14px; white-space: pre;">v</a><span style="font-family: monospace;font-size:14px; white-space: pre;">(</span><span class="mark-1#1" style="font-family: monospace;font-size:14px; white-space: pre;"><a target=_blank href="http://grepcode.com/file/repo1.maven.org/maven2/org.robolectric/android-all/5.0.0_r2-robolectric-0/android/app/ActivityThread.java#ActivityThread.0TAG" title="String TAG" class="hidden" style="padding: 0px; margin: 0px; color: rgb(0, 0, 0); text-decoration: none;">TAG</a></span><span style="font-family: monospace;font-size:14px; white-space: pre;">, </span><span class="strliteral" style="color: rgb(42, 0, 255); font-family: monospace;font-size:14px; white-space: pre;">"<<< done: "</span><span style="font-family: monospace;font-size:14px; white-space: pre;"> + </span><a target=_blank href="http://grepcode.com/file/repo1.maven.org/maven2/org.robolectric/android-all/5.0.0_r2-robolectric-0/android/app/ActivityThread.java#ActivityThread.H.codeToString%28int%29" title="android.app.ActivityThread.H.codeToString(int) : String" style="padding: 0px; margin: 0px; color: rgb(51, 102, 187); font-family: monospace;font-size:14px; white-space: pre;">codeToString</a><span style="font-family: monospace;font-size:14px; white-space: pre;">(</span><span class="mark-479#1" style="font-family: monospace;font-size:14px; white-space: pre;">msg</span><span style="font-family: monospace;font-size:14px; white-space: pre;">.</span><span class="mark-480#1" style="font-family: monospace;font-size:14px; white-space: pre;">what</span><span style="font-family: monospace;font-size:14px; white-space: pre;">));</span>
<span style="font-family: monospace;font-size:14px; white-space: pre;">}</span>
从Handler H对“LAUNCH_ACTIVITY”这个消息的处理可以知道,Activity的启动过程 由ActivityThread的handleLaunchActivity方法实现,他的源码如下:
private void handleLaunceActivity(ActivityClientRecord r,Iintent customIntent){ ... 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.statr; handleResumeActivity(r.token,false,r.isForward,!r.activity.mFinished&&!r. startsNotResumed); ... } ... }
从上面的源码可以看出,perforLaunchActivity方法最终完成了Activity对象的创建和启动过程,并且ActivityThread通过handleResumeActivity方法来调用被启动Activity的onResume这以生命周期方法。
perforLaunchActivity这个方法主要完成了如下几件事情:
1.从ActivityClientRecord中获取待启动的Activity的组件信息。
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对象:
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) { if (!mInstrumentation.onException(activity, e)) { throw new RuntimeException( "Unable to instantiate activity " + component + ": " + e.toString(), e); } }
至于Instrumentation的newActivity,他的实现比较简单,就是通过类加载器来创建Activity对象:
public Activity More ...newActivity(ClassLoader cl, String className, Intent intent) throws InstantiationException, IllegalAccessException, ClassNotFoundException { return (Activity)cl.loadClass(className).newInstance(); }
3,通过LoadedApk的makeApplication方法来尝试创建Application对象:
public Application More ...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(); if (!mPackageName.equals("android")) { initializeJavaContextClassLoader(); } ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this); 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); } } }
从makeApplication的实现可以看出,如果Application已经被创建过了,那么就不会再重复创建了,这也意味着一个应用只有一个Application对象,Application对象的创建也是通过Instrumentation来完成,这个过程和Activity的创建一样,都是通过类加载器来实现的,Application创建完毕后,系统会通过Instrumentation的callApplicationOnCreate来调用Application的onCreate方法。
4.创建ContextImpl对象并通过Activity的attach方法来完成一些重要的数据初始化:
ContextImpl是一个很重要的数据结构,他是Context的具体实现,Context中的大部分逻辑都是由ContextImpl来完成的。ContxetImpl是通过Activity的attach的方法和Activity建立关联的,除此之外,在attach方法中Activity还会完成Window的创建并建立自己和Window的关联,这样当Window接受到外部输入事件后,就可以将事件传递给Acivity
5.调用Activity的onCreate方法
mInstrumentation。callActivityOnCreate(activity,r.state),由于Activity的onCreate已经被调用,这也意味着Activity已经完成了整个启动过程。