本節要思考地問題 :java
系統內部是如何啓動一個Acitivity的 ?android
新的Activity對象是什麼時候建立的?app
Acitivity的onCreate()方法什麼時候被系統回調的?async
讓咱們帶着這些問題來學習Activity的建立啓動過程.ide
一種展現性組件,用來向用戶展現頁面,接受用戶的輸入與之交互。、函數
Activity
是由 Intent啓動,而 Intent 分爲 顯示Intent和 隱式Intent,顯示Intent是直接明確指定我想要啓動的另外一個活動,隱式Intent則多是指向多個其餘Activity
,好比咱們在使用qq聊天時,打開輸入框中的拍照功能,這時系統會彈出你手機中的好幾個相機應用讓你選擇。oop
Activity
有四種啓動模式,不一樣 模式的啓動方式有不一樣的效果。分別是 :學習
啓動一個Activity咱們最常使用的就是顯示調用Intent :ui
Intent intent = new Intent(this,TestActivity.class);
startActivity(intent);
複製代碼
startActivity()
方法在 Activity 中有其餘幾個重載方法,但最後都會調用 startActivityForResult()
方法:this
public void startActivityForResult(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());
}
...
...
}
複製代碼
注意到第4行中,又調用了 Instrumentation.execStarAtActivity()
方法。
從這個方法開始咱們一層一層地查看,原來啓動一個Activity須要這麼深的方法棧。
方法棧的最後由 ApplicationThread.scheduleLaunchActivity()
調用,這個類屬於 ActivityThread
的內部類,不太好找。貼一張 ApplicationThread 的類圖
scheduleLaunchActivity()
方法一探究竟 ,
ApplicationThread.scheduleLaunchAcitivity():
// we use token to identify this activity without having to send the
// activity itself back to the activity manager. (matters more with ipc)
@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);
}
複製代碼
看到最後一行經過 sendMessage()
發送了一條啓動Activity的消息交給Handler處理,這個 Handler也是ActivityThread的一個內部類,名叫H,好簡潔...
ActivityThread.H.sendMessage():
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+ ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}
複製代碼
咱們跳到名爲 H 的Handler中,看看它對這個消息是怎麼處理的 :
ActivityThread.H.handleMessage():
private class 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 void 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:
...
break;
case PAUSE_ACTIVITY:
...
break;
case PAUSE_ACTIVITY_FINISHING:
...
break;
}
}
}
複製代碼
在 case LAUNCH_ACTIVITY :中,調用了 handleLaunchActivity()
ActivityThread.handleLaunchActivity() :
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
...//省略部分代碼
if (localLOGV) Slog.v(
TAG, "Handling launch of " + r);
// Initialize before creating the activity
WindowManagerGlobal.initialize();
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);
...
... //省略部分代碼
} else {
...
}
}
複製代碼
第10行,由 performLaunchActivity(r, customIntent)
返回一個Activity對象,完成 Activity 對象的建立和啓動過程.
如今也就回答了咱們開頭提出的前兩個問題 :
第15行,由 handleResumeActivity()
調用 Activity生命週期中的 onResume()
方法。
ActivityThread.performLaunchActivity() 已經來到了最關鍵的步驟,這個函數主要完成了3件事情,咱們拆開一步一步看。
AcitivityClientRecord
對象中獲取待啓動的 Activity 的信息:private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//第一部分:從參數 AcitivityClientRecord 對象中獲取待啓動的 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);
}
}
複製代碼
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//第一部分:從參數 AcitivityClientRecord 對象中獲取待啓動的 Activity 的信息
...
...
//第二部分:經過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);
}
}
}
複製代碼
LoadedApk
的 makeApplication()
方法來嘗試建立Application對象 :private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//第一部分:從參數 AcitivityClientRecord 對象中獲取待啓動的 Activity 的信息
...
...
//第二部分:經過Instrumentation.newActivity()方法使用類加載器建立Activity對象
...
//第三部分:經過LoadedApk的makeApplication() 方法來嘗試建立Application對象
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
} ...
}
複製代碼
r.packeageInfo 是一個 LoadApk對象,用來加載 apk文件,進來看一下 makeApplication()方法 :
LoadApk.makeApplication():
/** * Local state maintained about a currently loaded .apk. * @hide */
public final class LoadedApk {
...
public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) {
if (mApplication != null) {
return mApplication;
}
Application app = null;
...
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;
...
...
return app;
}
}
複製代碼
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//第一部分:從參數 AcitivityClientRecord 對象中獲取待啓動的 Activity 的信息
...
...
//第二部分:經過Instrumentation.newActivity()方法使用類加載器建立Activity對象
...
//第三部分:經過LoadedApk的makeApplication() 方法來嘗試建立Application對象
...
//第四部分:建立Context對象,調用activity的attach方法來注入一些重要數據,進行activity的初始化
if (activity != null) {
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
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);
}
}
複製代碼
相信你們也看出來了,咱們日常使用的Context(App環境的上下文)就是經過 activity.attach() 方法與 Activity組件創建起聯繫的。
進入 attach()方法中,咱們還看到了 window也是在這裏進行初始化,並與 Activity 創建關聯,這樣當Window接收外部的輸入事件以後就能夠把事件傳給Activity.
Activity.attach() :
final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances, Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
mWindow = new PhoneWindow(this);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
if (info.uiOptions != 0) {
mWindow.setUiOptions(info.uiOptions);
}
mUiThread = Thread.currentThread();
mMainThread = aThread;
mInstrumentation = instr;
mToken = token;
mIdent = ident;
mApplication = application;
mIntent = intent;
mReferrer = referrer;
mComponent = intent.getComponent();
mActivityInfo = info;
mTitle = title;
mParent = parent;
mEmbeddedID = id;
mLastNonConfigurationInstances = lastNonConfigurationInstances;
if (voiceInteractor != null) {
if (lastNonConfigurationInstances != null) {
mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
} else {
mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
Looper.myLooper());
}
}
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
mWindowManager = mWindow.getWindowManager();
mCurrentConfig = config;
}
複製代碼
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//第一部分:從參數 AcitivityClientRecord 對象中獲取待啓動的 Activity 的信息
...
...
//第二部分:經過Instrumentation.newActivity()方法使用類加載器建立Activity對象
...
//第三部分:經過LoadedApk的makeApplication() 方法來嘗試建立Application對象
...
//第四部分:建立Context對象,調用activity的attach方法來注入一些重要數據,進行activity的初始化
...
//第五部分:調用Activity的onCreate()方法
activity.mCalled = false;
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;
if (!r.activity.mFinished) {
//調用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);
}
}
}
複製代碼
至此,Activity的啓動與建立,再到onCreate()方法的調用,咱們都已經分析完。
(完~) 謝謝你們瀏覽