關於Activity的源碼分析,看了足足有半個月,理由就是:
1:Activity源代碼不少,邏輯很複雜
2:下班再能加班學習,禮拜天抽空學習源碼
至於爲何看源碼:由於偶爾看到一句話:不懂Activity的onCreate的內部源碼,你敢說你是Android開發程序猿?!java
其實關於這篇文章,我想了好久,不太敢貿然寫,由於牽涉的類有點多而且複雜,怕理解出錯,給各位小夥伴帶來困擾,通過學習了兩個禮拜,學到了一點東西,總結一下。
首先Activity的啓動切入點有兩個,startActivity切入和ActivityThread的main方法切入,最終的效果都是開啓一個新的Activity。 本篇文章先從ActivityThread的main方法切入分析。
ActivityThread的Main方法入口android
一般咱們啓動一個App,首先都是先建立一個進程,而後AMS調度,進入到ActivityThread的main方法中,ActivityThread類一般就是咱們說的UI線程(主線程),一個進程對應一個ActivityThread,用於調度Activity的生命週期,Service的生命週期,以及調度Instrumentation的建立。看下main源碼:app
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
SamplingProfilerIntegration.start();ide
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);oop
Environment.initForCurrentUser();源碼分析
// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter());post
// Make sure TrustedCertificateStore looks in the right place for CA certificates
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);學習
Process.setArgV0("<pre-initialized>");ui
//注意點1:建立主線程的Looper
Looper.prepareMainLooper();this
//建立ActivityThread類
ActivityThread thread = new ActivityThread();
//注意點2:
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//開始主線程消息調度
Looper.loop();
//注意點3:不可以退出主線程Looper
throw new RuntimeException("Main thread loop unexpectedly exited");
}
經過Main方法,看下三個注意點:
建立主線程的Looper對象;在以前學習Handler,Looper源碼的時候,沒有初始化Looper,都可以實現消息調度。
調用了ActivityThread的attach方法
不可以退出主線程UI,若是若是退出,就報錯,由於咱們知道,開啓looper消息循環以後,Looper.loop()以後的代碼是不會執行的,由於若是退出了主線程,那麼App自動就死了,因此就提示報錯。
進入ActivityThread的attach方法。
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
ViewRootImpl.addFirstDrawHandler(new Runnable() {
@Override
public void run() {
ensureJitEnabled();
}
});
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
UserHandle.myUserId());
RuntimeInit.setApplicationObject(mAppThread.asBinder());
//建立得到IActivityManager的代理對象ActivityManagerService
final IActivityManager mgr = ActivityManager.getService();
try {
//建立applicaiton
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
....
}
先看下,ActivityManager.getService(),進入該方法:
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
//單例模式
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
//獲取一個關聯了系統服務ActivityManagerService的Binder對象
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
//獲取IActivityManager的代理對象,基於binder機制,經過調用代理對象的方法,從而使ActivityManagerService對象的方法被調用.
//注意:ActivityManagerService繼承自IActivityManager.Stub。
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
getService()內部調用的是IActivityManagerSingleton的get方法,大致來講,IActivityManagerSingleton是一個單例對象,再看onCreate方法,方法內部首先經過ServiceManager得到Activity_Service的註冊服務。返回IBinder對象,至此,咱們應該知道了,其實和底層交互數據的原理就是Binder機制。
先說下Binder機制,咱們知道Binder機制由四部分組成:客戶端,服務端,ServiceManager管理以及Binder驅動。其中前三個運行在用戶層,Binder驅動運行在內核層,而後服務端實現IBinder方法,成爲代理對象,底層的各類的ManagerService都會在ServiceManager,經過ServiceManager統一得到各類服務端Binder對象。至於Binder機制,建議各位同窗去看下Binder源碼。在此再也不贅述。
咱們知道ActivityManagerService繼承字IActivityManager.Stub,因此自己來講他就是一個Binder對象。因此getService()方法自己返回的就是一個代理對象,經過調用代理對象的方法,從而調用AMS(ActivityManagerService的簡稱)的方法。
接下來回到attach方法,調用了AMS的attachApplication方法,源碼示下:
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
......
if (app.instr != null) {
thread.bindApplication(processName, appInfo, providers,
app.instr.mClass,
profilerInfo, app.instr.mArguments,
app.instr.mWatcher,
app.instr.mUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(getGlobalConfiguration()), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial);
} else {
//經過代理對象ApplicationThread調用其方法bindApplication方法;
thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
null, null, null, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(getGlobalConfiguration()), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial);
}
.....
// See if the top visible activity is waiting to run in this process...
if (normalMode) {
try {
//注意點2:
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
....
}
首先看到上述代碼:調用了thread.bindApplication(….)方法,thread是個IApplicationThread代理對象,又是Binder機制。。。實際上,AMS向上層UI主線程的控制是經過ApplicationThread的調度,ApplicaitonThread是ActivityThread的內部類,繼承了IAppllication.Stub,是個Binder類,因此調用thread.bindApplicaiton(), 實際上調用的是ApplicationThread的bindApplication()方法;
至於注意點2: 咱們下文再分析
進入到ApplicationThread $ bindApplication :
public final void bindApplication(String processName, ApplicationInfo appInfo,
List<ProviderInfo> providers, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableBinderTracking, boolean trackAllocation,
boolean isRestrictedBackupMode, boolean persistent, Configuration config,
CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
String buildSerial) {
.....
sendMessage(H.BIND_APPLICATION, data);
}
發送Message, 繼續跟進:handleBindApplication :
private void handleBindApplication(AppBindData data) {
....
//獲取APK的相關信息,好比:包名,版本號等信息;
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
.....
//建立ContextImpl(該類繼承自抽象類Context)
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
updateLocaleListFromAppContext(appContext,
mResourcesManager.getConfiguration().getLocales());
.....
// Continue loading instrumentation.
if (ii != null) {
final ApplicationInfo instrApp = new ApplicationInfo();
ii.copyTo(instrApp);
instrApp.initForUser(UserHandle.myUserId());
// 獲取APP信息
final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
appContext.getClassLoader(), false, true, false);
final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
try {
final ClassLoader cl = instrContext.getClassLoader();
//注意點1:經過反射建立Instrumentation對象
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
}
......
try {
//注意點2:建立Application
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
.....
try {
//注意點3:調用Application的onCreate方法
mInstrumentation.callApplicationOnCreate(app);
}
......
}
看下注意點:
經過反射建立Instrumentation對象,首先,對於Instrumentation的做用,先不深談,咱們只要知道建立Instrumentation的位置。
data.info.makeApplication(…) 這裏data.info 也就是LoadedAPK類的對象。
調用了Instrumentation的callApplicationOnCreate方法。
首先說下注意點看,進入到LoadedApk $ makeApplication(…)
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
//整個應用內,只有一個Application對象
if (mApplication != null) {
return mApplication;
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
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")) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
"initializeJavaContextClassLoader");
initializeJavaContextClassLoader();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
//調用Instrumentation的newApplication方法。
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
}
......
}
上述代碼,首先判斷mApplication是否爲null, 不爲null,就直接返回,這就是爲何一個應用只有一個Application對象(單進程), 爲null的話,調用了Instrumentation的newApplication方法。
進入到Instrumentation $ newApplication方法
static public Application newApplication(Class<?> clazz, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
//經過反射建立了Application對象
Application app = (Application)clazz.newInstance();
app.attach(context);
return app;
}
newApplication作的事只有兩件,首先經過反射建立Application對象,而且調用其attach方法,返回該對象。再次注意一下:Application是在Instrumentation中建立的。
再回到ActivityThread的handleBindApplication方法,接下來看下注意點3:進入到Instrumentation $ callApplicationOnCreate方法:
public void callApplicationOnCreate(Application app) {
app.onCreate();
}
調用了,就一句話:調用了Application的onCreate方法。
解釋了:爲何咱們通常都在Application的onCreate方法中初始化一些第三方,由於它最先被建立啊!
至此Application的建立就完成了,那麼Activity頁面呢?
回到AMS的attachApplicationLocked方法:看下注意點2,調用了ActivityStackSupervisor類的attachApplicationLocked方法:
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
....
//
if (realStartActivityLocked(hr, app, true, true)) {
didSomething = true;
}
....
}
進入realStartActivityLocked(….)方法,
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
......
/*
經過binder機制,經過代理調用ApplicationThread的scheduleLaunchActivity方法。將啓動Activity的操做交給ApplicationThread類
*/
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
// TODO: Have this take the merged configuration instead of separate global and
// override configs.
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
r.persistentState, results, newIntents, !andResume,
mService.isNextTransitionForward(), profilerInfo);
.......
}
調用了Application的ApplicationThread的scheduleLaunchActivity(…)方法,進入 ApplicationThread$scheduleLaunchActivity(…):
@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);
//用於封裝啓動Activity一些參數值
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);
}
發送消息,進入ActivityThead的handleLaunchActivity方法:
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
......
//注意點1:啓動Activity
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
Bundle oldState = r.state;
// 注意點2:
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
......
}
上述代碼標註了兩個注意點,先看下注意點1的方法, 進入 performLaunchActivity方法:
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
......
//獲取要啓動的Activity的ComponentName對象
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
.......
//建立Activity的上下文環境(ContentImpl繼承自Context)
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
//經過類加載器建立Activity對象
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
.......
}
//獲取Application對象
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
......
//初始化Activity類裏的一些數據
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, r.configCallback);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
checkAndBlockForNetworkAccess();
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
//Activity設置主題
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
//啓動Activity
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onCreate()");
}
r.activity = activity;
r.stopped = true;
//判斷是不是結束Activity
if (!r.activity.mFinished) {
activity.performStart();
r.stopped = false;
}
if (!r.activity.mFinished) {
if (r.isPersistable()) {
if (r.state != null || r.persistentState != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
r.persistentState);
}
} else if (r.state != null) { //剛進來的Activity bundle數據爲null
//r.state 也就是咱們保存的Bundle對象,要恢復的數據
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
}
}
......
}
在該方法裏,比較重要的就是首先調用了Instrumentation的newActivity方法,進入到該方法,
public Activity newActivity(Class<?> clazz, Context context,
IBinder token, Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
Object lastNonConfigurationInstance) throws InstantiationException,
IllegalAccessException {
Activity activity = (Activity)clazz.newInstance();
ActivityThread aThread = null;
activity.attach(context, aThread, this, token, 0 /* ident */, application, intent,
info, title, parent, id,
(Activity.NonConfigurationInstances)lastNonConfigurationInstance,
new Configuration(), null /* referrer */, null /* voiceInteractor */,
null /* window */, null /* activityConfigCallback */);
return activity;
}
經過反射建立了Activity。至此咱們在注意下:在Instrumentation中建立Activity對象。
返回performLaunchActivity方法:建立Activity以後,設置主題,而後調用了Instrumentation的callActivityOnCreate方法,進入該方法:
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
activity.performCreate(icicle);
postPerformCreate(activity);
}
調用了performCreate方法,進入Activity $ performCreate :
final void performCreate(Bundle icicle) {
restoreHasCurrentPermissionRequest(icicle);
// onCreate方法回調
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
(⊙﹏⊙),至此onCreate方法算是執行到了,那麼onStart和onResume方法呢?繼續探究。。。
再次回到 performLaunchActivity方法中, 調用了 performStart()方法,進入方法內:
final void performStart() {
.....
mInstrumentation.callActivityOnStart(this);
.....
}
接下來仍是經過調用了Instrumentation的callActivityOnStart()方法,內部再調用Activity的onStart()方法。
至此onStart方法調用了,那麼 onResume呢? 繼續深究。。。
返回到handleLaunchActivity方法中,看下注意點2,進入到handleResumeActivity方法內:
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
......
r = performResumeActivity(token, clearHide, reason);
.......
// Tell the activity manager we have resumed.
if (reallyResume) {
try {
//Activity A 跳轉到 Activity B ,當ActivityB建立並顯示完畢以後,開始Activity A的onPauseme
ActivityManager.getService().activityResumed(token);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
......
進入到performResumeActivity方法:
public final ActivityClientRecord performResumeActivity(IBinder token,
boolean clearHide, String reason) {
......
r.activity.performResume();
......
}
進入到Activity $ performResume:
final void performResume() {
//是不是從新啓動Activity
performRestart();
mFragments.execPendingActions();
mLastNonConfigurationInstances = null;
mCalled = false;
// mResumed is set by the instrumentation
mInstrumentation.callActivityOnResume(this);
.....
}
看見調用了Instrumentation的callActivityOnResume方法,仍是經過Instrumentation間接調用Activity的回調方法。
public void callActivityOnResume(Activity activity) {
activity.mResumed = true;
//調用了Activity的onResume方法:
activity.onResume();
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=0; i<N; i++) {
final ActivityMonitor am = mActivityMonitors.get(i);
am.match(activity, activity, activity.getIntent());
}
}
}
}
至此開啓APP從ActivityThread的main方法入口開始,Activity的啓動流程就分析完了。
下一篇分析另外一個切入點:Activity的startActivity方法以及Activity的銷燬流程(finish)
Android進階3:Activity源碼分析(2) —— Activity啓動和銷燬流程(8.0)
若是文章有錯,感謝小夥伴指正,謝謝O(∩_∩)O。