Android源码分析-Activity的启动过程

前言

Activity是Android中一个很重要的概念,堪称四大组件之首,关于Activity有很多内容,比如生命周期和启动Flags,这二者想要说清楚,恐怕又要写两篇长文,更何况分析它们的源码呢。不过本文的侧重点不是它们,我要介绍的是一个Activity典型的启动过程,本文会从源码的角度对其进行分析。我们知道,当startActivity被调用的时候,可以启动一个Activity,但是你知道这个Activity是如何被启动的吗?每个Activity也是一个对象,你知道这个对象是啥时候被创建的吗(也就是说它的构造方法是什么时候被调用的)?为什么onCreate是Activity的执行入口?所有的这一切都被系统封装好了,对我们来说是透明的,我们使用的时候仅仅是传递一个intent然后startActivity就可以达到目的了,不过,阅读了本文以后,你将会了解它的背后到底做了哪些事情。在分析之前,我先介绍几个类:

  1. Activity:这个大家都熟悉,startActivity方法的真正实现在Activity中
  2. Instrumentation:用来辅助Activity完成启动Activity的过程
  3. ActivityThread(包含ApplicationThread + ApplicationThreadNative + IApplicationThread):真正启动Activity的实现都在这里

源码分析

首先看入口

code:Activity#startActivity

[java]  view plain copy
  1. @Override  
  2. public void startActivity(Intent intent) {  
  3.     startActivity(intent, null);  
  4. }  
  5.   
  6. @Override  
  7. public void startActivity(Intent intent, Bundle options) {  
  8.     if (options != null) {  
  9.         startActivityForResult(intent, -1, options);  
  10.     } else {  
  11.         // Note we want to go through this call for compatibility with  
  12.         // applications that may have overridden the method.  
  13.         startActivityForResult(intent, -1);  
  14.     }  
  15. }  
  16.   
  17. public void startActivityForResult(Intent intent, int requestCode) {  
  18.     startActivityForResult(intent, requestCode, null);  
  19. }  

说明:显然,从上往下,最终都是由startActivityForResult来实现的

接着看

code:Activity#startActivityForResult

[java]  view plain copy
  1. public void startActivityForResult(Intent intent, int requestCode, Bundle options) {  
  2.     //一般的Activity其mParent为null,mParent常用在ActivityGroup中,ActivityGroup已废弃  
  3.     if (mParent == null) {  
  4.         //这里会启动新的Activity,核心功能都在mMainThread.getApplicationThread()中完成  
  5.         Instrumentation.ActivityResult ar =  
  6.             mInstrumentation.execStartActivity(  
  7.                 this, mMainThread.getApplicationThread(), mToken, this,  
  8.                 intent, requestCode, options);  
  9.         if (ar != null) {  
  10.             //发送结果,即onActivityResult会被调用  
  11.             mMainThread.sendActivityResult(  
  12.                 mToken, mEmbeddedID, requestCode, ar.getResultCode(),  
  13.                 ar.getResultData());  
  14.         }  
  15.         if (requestCode >= 0) {  
  16.             // If this start is requesting a result, we can avoid making  
  17.             // the activity visible until the result is received.  Setting  
  18.             // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the  
  19.             // activity hidden during this time, to avoid flickering.  
  20.             // This can only be done when a result is requested because  
  21.             // that guarantees we will get information back when the  
  22.             // activity is finished, no matter what happens to it.  
  23.             mStartedActivity = true;  
  24.         }  
  25.   
  26.         final View decor = mWindow != null ? mWindow.peekDecorView() : null;  
  27.         if (decor != null) {  
  28.             decor.cancelPendingInputEvents();  
  29.         }  
  30.         // TODO Consider clearing/flushing other event sources and events for child windows.  
  31.     } else {  
  32.         //在ActivityGroup内部的Activity调用startActivity的时候会走到这里,内部处理逻辑和上面是类似的  
  33.         if (options != null) {  
  34.             mParent.startActivityFromChild(this, intent, requestCode, options);  
  35.         } else {  
  36.             // Note we want to go through this method for compatibility with  
  37.             // existing applications that may have overridden it.  
  38.             mParent.startActivityFromChild(this, intent, requestCode);  
  39.         }  
  40.     }  
  41. }  

说明:上述代码关键点都有注释了,可以发现,真正打开activity的实现在Instrumentation的execStartActivity方法中,去看看

code:Instrumentation#execStartActivity

[java]  view plain copy
  1. public ActivityResult execStartActivity(  
  2.         Context who, IBinder contextThread, IBinder token, Activity target,  
  3.         Intent intent, int requestCode, Bundle options) {  
  4.     //核心功能在这个whoThread中完成,其内部scheduleLaunchActivity方法用于完成activity的打开  
  5.     IApplicationThread whoThread = (IApplicationThread) contextThread;  
  6.     if (mActivityMonitors != null) {  
  7.         synchronized (mSync) {  
  8.             //先查找一遍看是否存在这个activity  
  9.             final int N = mActivityMonitors.size();  
  10.             for (int i=0; i<N; i++) {  
  11.                 final ActivityMonitor am = mActivityMonitors.get(i);  
  12.                 if (am.match(who, null, intent)) {  
  13.                     //如果找到了就跳出循环  
  14.                     am.mHits++;  
  15.                     //如果目标activity无法打开,直接return  
  16.                     if (am.isBlocking()) {  
  17.                         return requestCode >= 0 ? am.getResult() : null;  
  18.                     }  
  19.                     break;  
  20.                 }  
  21.             }  
  22.         }  
  23.     }  
  24.     try {  
  25.         intent.migrateExtraStreamToClipData();  
  26.         intent.prepareToLeaveProcess();  
  27.         //这里才是真正打开activity的地方,核心功能在whoThread中完成。  
  28.         int result = ActivityManagerNative.getDefault()  
  29.             .startActivity(whoThread, who.getBasePackageName(), intent,  
  30.                     intent.resolveTypeIfNeeded(who.getContentResolver()),  
  31.                     token, target != null ? target.mEmbeddedID : null,  
  32.                     requestCode, 0nullnull, options);  
  33.         //这个方法是专门抛异常的,它会对结果进行检查,如果无法打开activity,  
  34.         //则抛出诸如ActivityNotFoundException类似的各种异常  
  35.         checkStartActivityResult(result, intent);  
  36.     } catch (RemoteException e) {  
  37.     }  
  38.     return null;  
  39. }  

说明:我想再说一下这个方法checkStartActivityResult,它也专业抛异常的,看代码,相信大家对下面的异常信息不陌生吧,就是它干的,其中最熟悉的非Unable to find explicit activity class莫属了,如果你在xml中没有注册目标activity,此异常将会抛出。

[java]  view plain copy
  1. /*package*/ static void checkStartActivityResult(int res, Object intent) {  
  2.     if (res >= ActivityManager.START_SUCCESS) {  
  3.         return;  
  4.     }  
  5.       
  6.     switch (res) {  
  7.         case ActivityManager.START_INTENT_NOT_RESOLVED:  
  8.         case ActivityManager.START_CLASS_NOT_FOUND:  
  9.             if (intent instanceof Intent && ((Intent)intent).getComponent() != null)  
  10.                 throw new ActivityNotFoundException(  
  11.                         "Unable to find explicit activity class "  
  12.                         + ((Intent)intent).getComponent().toShortString()  
  13.                         + "; have you declared this activity in your AndroidManifest.xml?");  
  14.             throw new ActivityNotFoundException(  
  15.                     "No Activity found to handle " + intent);  
  16.         case ActivityManager.START_PERMISSION_DENIED:  
  17.             throw new SecurityException("Not allowed to start activity "  
  18.                     + intent);  
  19.         case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:  
  20.             throw new AndroidRuntimeException(  
  21.                     "FORWARD_RESULT_FLAG used while also requesting a result");  
  22.         case ActivityManager.START_NOT_ACTIVITY:  
  23.             throw new IllegalArgumentException(  
  24.                     "PendingIntent is not an activity");  
  25.         default:  
  26.             throw new AndroidRuntimeException("Unknown error code "  
  27.                     + res + " when starting " + intent);  
  28.     }  
  29. }  

接下来我们要去看看IApplicationThread,因为核心功能由其内部的scheduleLaunchActivity方法来完成,由于IApplicationThread是个接口,所以,我们需要找到它的实现类,我已经帮大家找到了,它就是ActivityThread中的内部类ApplicationThread,看下它的继承关系:

private class ApplicationThread extends ApplicationThreadNative;

public abstract class ApplicationThreadNative extends Binder implements IApplicationThread;

可以发现,ApplicationThread还是间接实现了IApplicationThread接口,先看下这个类的结构

Android源码分析-Activity的启动过程_第1张图片

看完ApplicationThread的大致结构,我们应该能够猜测到,Activity的生命周期中的resume、newIntent、pause、stop等事件都是由它触发的,事实上,的确是这样的。这里,我们为了说明问题,仅仅看scheduleLaunchActivity方法

code:ApplicationThread#scheduleLaunchActivity

[java]  view plain copy
  1. public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,  
  2.         ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,  
  3.         int procState, Bundle state, List<ResultInfo> pendingResults,  
  4.         List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,  
  5.         String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {  
  6.   
  7.     updateProcessState(procState, false);  
  8.   
  9.     ActivityClientRecord r = new ActivityClientRecord();  
  10.   
  11.     r.token = token;  
  12.     r.ident = ident;  
  13.     r.intent = intent;  
  14.     r.activityInfo = info;  
  15.     r.compatInfo = compatInfo;  
  16.     r.state = state;  
  17.   
  18.     r.pendingResults = pendingResults;  
  19.     r.pendingIntents = pendingNewIntents;  
  20.   
  21.     r.startsNotResumed = notResumed;  
  22.     r.isForward = isForward;  
  23.   
  24.     r.profileFile = profileName;  
  25.     r.profileFd = profileFd;  
  26.     r.autoStopProfiler = autoStopProfiler;  
  27.   
  28.     updatePendingConfiguration(curConfig);  
  29.   
  30.     queueOrSendMessage(H.LAUNCH_ACTIVITY, r);  
  31. }  

说明:上述代码很好理解,构造一个activity记录,然后发送一个消息,所以,我们要看看Handler是如何处理这个消息的,现在转到这个Handler,它有个很短的名字叫做H

code:ActivityThread#H

[java]  view plain copy
  1. //这个类太长,我只帖出了我们用到的部分  
  2. private class H extends Handler {  
  3.   
  4.     public void handleMessage(Message msg) {  
  5.         if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));  
  6.         switch (msg.what) {  
  7.             //这里处理LAUNCH_ACTIVITY消息类型  
  8.             case LAUNCH_ACTIVITY: {  
  9.                 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");  
  10.                 ActivityClientRecord r = (ActivityClientRecord)msg.obj;  
  11.   
  12.                 r.packageInfo = getPackageInfoNoCheck(  
  13.                         r.activityInfo.applicationInfo, r.compatInfo);  
  14.                 //这里处理startActivity消息  
  15.                 handleLaunchActivity(r, null);  
  16.                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);  
  17.             } break;  
  18.             case RELAUNCH_ACTIVITY: {  
  19.                 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");  
  20.                 ActivityClientRecord r = (ActivityClientRecord)msg.obj;  
  21.                 handleRelaunchActivity(r);  
  22.                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);  
  23.             } break;  
  24.             case PAUSE_ACTIVITY:  
  25.                 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");  
  26.                 handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);  
  27.                 maybeSnapshot();  
  28.                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);  
  29.                 break;  
  30.             ...  
  31.         }  
  32. }  

说明:看来还要看handleLaunchActivity

code:ActivityThread#handleLaunchActivity

[java]  view plain copy
  1. private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {  
  2.     // If we are getting ready to gc after going to the background, well  
  3.     // we are back active so skip it.  
  4.     unscheduleGcIdler();  
  5.   
  6.     if (r.profileFd != null) {  
  7.         mProfiler.setProfiler(r.profileFile, r.profileFd);  
  8.         mProfiler.startProfiling();  
  9.         mProfiler.autoStopProfiler = r.autoStopProfiler;  
  10.     }  
  11.   
  12.     // Make sure we are running with the most recent config.  
  13.     handleConfigurationChanged(nullnull);  
  14.   
  15.     if (localLOGV) Slog.v(  
  16.         TAG, "Handling launch of " + r);  
  17.     //终于到底了,大家都有点不耐烦了吧,从方法名可以看出,  
  18.     //performLaunchActivity真正完成了activity的调起,  
  19.     //同时activity会被实例化,并且onCreate会被调用  
  20.     Activity a = performLaunchActivity(r, customIntent);  
  21.   
  22.     if (a != null) {  
  23.         r.createdConfig = new Configuration(mConfiguration);  
  24.         Bundle oldState = r.state;  
  25.         //看到没,目标activity的onResume会被调用  
  26.         handleResumeActivity(r.token, false, r.isForward,  
  27.                 !r.activity.mFinished && !r.startsNotResumed);  
  28.   
  29.         if (!r.activity.mFinished && r.startsNotResumed) {  
  30.             // The activity manager actually wants this one to start out  
  31.             // paused, because it needs to be visible but isn't in the  
  32.             // foreground.  We accomplish this by going through the  
  33.             // normal startup (because activities expect to go through  
  34.             // onResume() the first time they run, before their window  
  35.             // is displayed), and then pausing it.  However, in this case  
  36.             // we do -not- need to do the full pause cycle (of freezing  
  37.             // and such) because the activity manager assumes it can just  
  38.             // retain the current state it has.  
  39.             try {  
  40.                 r.activity.mCalled = false;  
  41.                 //同时,由于新activity被调起了,原activity的onPause会被调用  
  42.                 mInstrumentation.callActivityOnPause(r.activity);  
  43.                 // We need to keep around the original state, in case  
  44.                 // we need to be created again.  But we only do this  
  45.                 // for pre-Honeycomb apps, which always save their state  
  46.                 // when pausing, so we can not have them save their state  
  47.                 // when restarting from a paused state.  For HC and later,  
  48.                 // we want to (and can) let the state be saved as the normal  
  49.                 // part of stopping the activity.  
  50.                 if (r.isPreHoneycomb()) {  
  51.                     r.state = oldState;  
  52.                 }  
  53.                 if (!r.activity.mCalled) {  
  54.                     throw new SuperNotCalledException(  
  55.                         "Activity " + r.intent.getComponent().toShortString() +  
  56.                         " did not call through to super.onPause()");  
  57.                 }  
  58.   
  59.             } catch (SuperNotCalledException e) {  
  60.                 throw e;  
  61.   
  62.             } catch (Exception e) {  
  63.                 if (!mInstrumentation.onException(r.activity, e)) {  
  64.                     throw new RuntimeException(  
  65.                             "Unable to pause activity "  
  66.                             + r.intent.getComponent().toShortString()  
  67.                             + ": " + e.toString(), e);  
  68.                 }  
  69.             }  
  70.             r.paused = true;  
  71.         }  
  72.     } else {  
  73.         // If there was an error, for any reason, tell the activity  
  74.         // manager to stop us.  
  75.         try {  
  76.             ActivityManagerNative.getDefault()  
  77.                 .finishActivity(r.token, Activity.RESULT_CANCELED, null);  
  78.         } catch (RemoteException ex) {  
  79.             // Ignore  
  80.         }  
  81.     }  
  82. }  

说明:关于原activity和新activity之间的状态同步,如果大家感兴趣可以自己研究下,因为逻辑太复杂,我没法把所有问题都说清楚,否则就太深入细节而淹没了整体逻辑,研究源码要的就是清楚整体逻辑。下面看最后一个方法,这个方法是activity的启动过程的真正实现。
code:ActivityThread#performLaunchActivity

[java]  view plain copy
  1. private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {  
  2.     // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");  
  3.   
  4.     ActivityInfo aInfo = r.activityInfo;  
  5.     if (r.packageInfo == null) {  
  6.         r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,  
  7.                 Context.CONTEXT_INCLUDE_CODE);  
  8.     }  
  9.     //首先从intent中解析出目标activity的启动参数  
  10.     ComponentName component = r.intent.getComponent();  
  11.     if (component == null) {  
  12.         component = r.intent.resolveActivity(  
  13.             mInitialApplication.getPackageManager());  
  14.         r.intent.setComponent(component);  
  15.     }  
  16.   
  17.     if (r.activityInfo.targetActivity != null) {  
  18.         component = new ComponentName(r.activityInfo.packageName,  
  19.                 r.activityInfo.targetActivity);  
  20.     }  
  21.   
  22.     Activity activity = null;  
  23.     try {  
  24.         java.lang.ClassLoader cl = r.packageInfo.getClassLoader();  
  25.         //用ClassLoader(类加载器)将目标activity的类通过类名加载进来并调用newInstance来实例化一个对象  
  26.         //其实就是通过Activity的无参构造方法来new一个对象,对象就是在这里new出来的。  
  27.         activity = mInstrumentation.newActivity(  
  28.                 cl, component.getClassName(), r.intent);  
  29.         StrictMode.incrementExpectedActivityCount(activity.getClass());  
  30.         r.intent.setExtrasClassLoader(cl);  
  31.         if (r.state != null) {  
  32.             r.state.setClassLoader(cl);  
  33.         }  
  34.     } catch (Exception e) {  
  35.         if (!mInstrumentation.onException(activity, e)) {  
  36.             throw new RuntimeException(  
  37.                 "Unable to instantiate activity " + component  
  38.                 + ": " + e.toString(), e);  
  39.         }  
  40.     }  
  41.   
  42.     try {  
  43.         Application app = r.packageInfo.makeApplication(false, mInstrumentation);  
  44.   
  45.         if (localLOGV) Slog.v(TAG, "Performing launch of " + r);  
  46.         if (localLOGV) Slog.v(  
  47.                 TAG, r + ": app=" + app  
  48.                 + ", appName=" + app.getPackageName()  
  49.                 + ", pkg=" + r.packageInfo.getPackageName()  
  50.                 + ", comp=" + r.intent.getComponent().toShortString()  
  51.                 + ", dir=" + r.packageInfo.getAppDir());  
  52.   
  53.         if (activity != null) {  
  54.             Context appContext = createBaseContextForActivity(r, activity);  
  55.             CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());  
  56.             Configuration config = new Configuration(mCompatConfiguration);  
  57.             if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "  
  58.                     + r.activityInfo.name + " with config " + config);  
  59.             activity.attach(appContext, this, getInstrumentation(), r.token,  
  60.                     r.ident, app, r.intent, r.activityInfo, title, r.parent,  
  61.                     r.embeddedID, r.lastNonConfigurationInstances, config);  
  62.   
  63.             if (customIntent != null) {  
  64.                 activity.mIntent = customIntent;  
  65.             }  
  66.             r.lastNonConfigurationInstances = null;  
  67.             activity.mStartedActivity = false;  
  68.             int theme = r.activityInfo.getThemeResource()  
  69.             if (theme != 0) {  
  70.                 activity.setTheme(theme);  
  71.             }  
  72.   
  73.             activity.mCalled = false;  
  74.             //目标activity的onCreate被调用了,到此为止,Activity被启动了,接下来的流程就是Activity的生命周期了,  
  75.             //本文之前已经提到,其生命周期的各种状态的切换由ApplicationThread内部来完成  
  76.             mInstrumentation.callActivityOnCreate(activity, r.state);  
  77.             if (!activity.mCalled) {  
  78.                 throw new SuperNotCalledException(  
  79.                     "Activity " + r.intent.getComponent().toShortString() +  
  80.                     " did not call through to super.onCreate()");  
  81.             }  
  82.             r.activity = activity;  
  83.             r.stopped = true;  
  84.             if (!r.activity.mFinished) {  
  85.                 activity.performStart();  
  86.                 r.stopped = false;  
  87.             }  
  88.             if (!r.activity.mFinished) {  
  89.                 if (r.state != null) {  
  90.                     mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);  
  91.                 }  
  92.             }  
  93.             if (!r.activity.mFinished) {  
  94.                 activity.mCalled = false;  
  95.                 mInstrumentation.callActivityOnPostCreate(activity, r.state);  
  96.                 if (!activity.mCalled) {  
  97.                     throw new SuperNotCalledException(  
  98.                         "Activity " + r.intent.getComponent().toShortString() +  
  99.                         " did not call through to super.onPostCreate()");  
  100.                 }  
  101.             }  
  102.         }  
  103.         r.paused = true;  
  104.   
  105.         mActivities.put(r.token, r);  
  106.   
  107.     } catch (SuperNotCalledException e) {  
  108.         throw e;  
  109.   
  110.     } catch (Exception e) {  
  111.         if (!mInstrumentation.onException(activity, e)) {  
  112.             throw new RuntimeException(  
  113.                 "Unable to start activity " + component  
  114.                 + ": " + e.toString(), e);  
  115.         }  
  116.     }  
  117.   
  118.     return activity;  
  119. }  

总结

相信当你看到这里的时候,你对Activity的启动过程应该有了一个感性的认识。Activity很复杂,特性很多,本文没法对各个细节进行深入分析,而且就算真的对各个细节都进行了深入分析,那文章要有多长啊,还有人有耐心看下去吗?希望本文能够给大家带来一些帮助,谢谢大家阅读。

你可能感兴趣的:(Android源码分析-Activity的启动过程)