通常情況下,我們在顯式呼叫Activity的情況下,只需要通過如下程式碼就能啟動一個Activity:
Intent intent = new Intent(this, TestActivity.class);
startActivity(intent);
複製程式碼
通過上面的程式碼就能啟動一個Activity,之後新的Activity就能被系統展示給使用者。 那麼系統是如何啟動一個Activity? 新的Activity物件是在什麼情況下被建立的? onCreate是在什麼時機被系統回撥的?
帶著這些問題,我們來一起分析下Activity的啟動過程。
我們通過startActivity開始分析:
public void startActivityForResult(@RequiresPermission 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());
}
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;
}
cancelInputsAndStartExitTransition(options);
// TODO Consider clearing/flushing other event sources and events for child windows.
} 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);
}
}
}
複製程式碼
通過上面的程式碼可以發現呼叫了mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, this,intent, requestCode, options)
這個方法:
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
Uri referrer = target != null ? target.onProvideReferrer() : null;
if (referrer != null) {
intent.putExtra(Intent.EXTRA_REFERRER, referrer);
}
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(who);
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) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
複製程式碼
通過上面的程式碼可以發現,啟動Activity的真正實現是ActivityManangerNative.getDefault()
的startActivity
方法來完成的。
public abstract class ActivityManagerNative extends Binder implements IActivityManager{
}
複製程式碼
通過觀察ActivityManangerNative可以發現繼承了Binder
並實現了IActivityManager
,所以ActivityManangerNative
是一個Binder物件:
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;
}
};
複製程式碼
通過ActivityManangerNative.getDefault()
方法可以看到這是一個單例的封裝:
IBinder b = ServiceManager.getService("activity");
複製程式碼
通過ServiceManger來獲取到真正的Binder物件並返回,而這個物件就是ActivityManagerService
,那麼怎麼確定就是它呢?可以參考PackageManagerService的建立過程。
到此為止,Activity的啟動過程就轉到了ActivityManagerService中(不同版本的原始碼略有區別):
ActivityManagerService.startActivity
-> ActivityManagerService.startActivityAsUser
-> ActivityStarter.startActivityMayWait
-> ActivityStarter.startActivityLocked
-> ActivityStarter.startActivityUnchecked
-> ActivityStackSupervisor.resumeFocusedStackTopActivityLocked
-> ActivityStack.resumeTopActivityUncheckedLocked
-> ActivityStack.resumeTopActivityInnerLocked
-> ActivityStackSupervisor.startSpecificActivityLocked
-> ActivityStackSupervisor.realStartActivityLocked
複製程式碼
通過不斷的跳轉最終跳轉到了ActivityStackSupervisor.realStartActivityLocked
方法中:
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);
複製程式碼
app.thread
是IApplicationThread
的型別:
public interface IApplicationThread extends IInterface {}
複製程式碼
而IApplicationThread
是IInterface
型別,所以它也是一個Binder型別的介面,從IApplicationThread
的宣告可以看出,其中包含了大量的啟動、停止Activity的介面,還包含啟動和停止Service的介面。通過宣告可以猜測這個Binder介面完成了大量的Activity和Service啟動和停止相關的功能。
那麼IApplicationThread
的實現又是什麼呢?
我們通過追溯thread可以知道是ApplicationThread
:
@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();
r.token = token;
r.ident = ident;
r.intent = intent;
r.referrer = referrer;
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;
r.overrideConfig = overrideConfig;
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);
}
複製程式碼
這個方法很簡單,就是構造了ActivityClientRecord
並賦值,之後傳送一個訊息給Handler,這個Handler就是主執行緒的H:
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;
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
Activity a = performLaunchActivity(r, customIntent);
}
複製程式碼
最終performLaunchActivity
完成了Activity物件的建立和啟動過程。
這個方法主要完成了這幾個操作:
-
通過
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); } 複製程式碼
-
通過類載入器建立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); } } public Activity newActivity(ClassLoader cl, String className, Intent intent) throws InstantiationException, IllegalAccessException, ClassNotFoundException { return (Activity)cl.loadClass(className).newInstance(); } 複製程式碼
-
通過makeApplication嘗試建立Application
Application app = r.packageInfo.makeApplication(false, mInstrumentation); 複製程式碼
從makeApplication中也可以看到如果Application已經存在了,那麼就不會在建立Application,保證一個應用只有一個Application物件。Application也是通過類載入器來建立的。
instrumentation.callApplicationOnCreate(app); 複製程式碼
當Application第一次建立之後就會呼叫Application的onCreate方法,這就是為什麼當啟動一個App的時候,Application會被首先呼叫的原因。
-
建立ContextImpl物件並通過Activity的attach方法來完成一系列操作
Context appContext = createBaseContextForActivity(r, activity); CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager()); Configuration config = new Configuration(mCompatConfiguration); if (r.overrideConfig != null) { config.updateFrom(r.overrideConfig); } if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity " + r.activityInfo.name + " with config " + config); 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); 複製程式碼
attach方法會關聯ContextImpl物件,還會關聯Window物件,並建立自己和Window物件的關聯。
-
呼叫Activity的onCreate方法
mInstrumentation.callActivityOnCreate(activity, r.state); -> activity.performCreate(icicle); final void performCreate(Bundle icicle) { restoreHasCurrentPermissionRequest(icicle); onCreate(icicle); mActivityTransitionState.readState(icicle); performCreateCommon(); } 複製程式碼
最終呼叫了我們熟悉的onCreate的生命週期中,此時Activity就完成了整個的啟動過程。