四大組件的運行狀態
一、Activity的工作過程
Activity作爲很重要的一個組件,其內部工作過程系統做了很多的封裝,這使得啓動一個Activity變得異常簡單。在顯示調用的情況下,只需要通過如下代碼即可完成:
Intent intent = new Intent(this, TestActivity.class);
startActivity(intent);
通過上面的代碼即可啓動一個具體的Activity了,然後新的Activity就會被系統啓動並展示在用戶的眼前。這個過程對於Android開發者再熟悉不過了,這也是很理所當然的事,但是有沒有想過系統內部到底是如何啓動Activity的呢?比如新Activity的對象是在何時創建的?Activity的onCreate方法又是在何時被系統回調的呢?在日常開發中是不需要了解系統的底層工作原理的,但是如果想在技術的領域更上一層樓,就很有必要知道系統的工作原理了。
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {//我們只需要關係這部分邏輯即可
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);//調用到了Instrumention裏面的execStartActivity方法。
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);
}
}
}
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);
ActivityResult result = null;
if (am.ignoreMatchingSpecificIntents()) {
result = am.onStartActivity(intent);
}
if (result != null) {
am.mHits++;
return result;
} else 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 = ActivityTaskManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);//可以看到這裏通過Binder調用到了AMS中去了
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
我們看下ActivityTaskManager.getService()代碼:
/** @hide */
public static IActivityTaskManager getService() {
return IActivityTaskManagerSingleton.get();
}
private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
new Singleton<IActivityTaskManager>() {
@Override
protected IActivityTaskManager create() {
//public static final String ACTIVITY_TASK_SERVICE = "activity_task";
final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);//這裏就拿到了服務的Binder類
return IActivityTaskManager.Stub.asInterface(b);//和之前的AIDL一樣,將服務端Binder轉化爲IActivityTaskManager,可以直接在本地調用到AMS中的方法了。
}
};
總結:到這裏,啓動的邏輯就通過IPC轉移到了AMS中了。我們只需要看AMS中的startActivity方法即可。
在分析AMS的startActivity方法之前,我們先看下Instrumentation中的execStartActivity方法中有 checkStartActivityResult(result, intent); 這一行代碼。直觀上看這個是檢查activity的啓動結果(實際也是如此的),代碼如下:
從上面的代碼看出,checkStartActivityResult方法作用很明顯,就是檢查啓動Activity的結果。當無法正確啓動一個Activity的時候,就是拋出異常信息。
接着我們繼續分析AMS中的startActivity方法:
@Override
public int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
//public ActivityTaskManagerService mActivityTaskManager;定義
return mActivityTaskManager.startActivity(caller, callingPackage, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions);
//可以看到調用到ActivityTaskManagerService 中去了
}
備註:在Android9.0上的代碼和書上的有些差異,但是流程都差不多。
可以看出,最後又轉移到了ActivityStarter的startActivityMayWait方法中,在startActivityMayWait中又調用了startActivityLocked方法,在startActivityLocked中又調用了startActivityUnchecked,緊接着有調用了resumeTopActivityUncheckedLocked方法,這個時候啓動過程已經從ActivityStackSupervisor轉移到了ActivityStack,可以看如下代碼:
@GuardedBy("mService")
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
if (mInResumeTopActivity) {
// Don't even start recursing.
return false;
}
boolean result = false;
try {
// Protect against recursion.
mInResumeTopActivity = true;
result = resumeTopActivityInnerLocked(prev, options);
// When resuming the top activity, it may be necessary to pause the top activity (for
// example, returning to the lock screen. We suppress the normal pause logic in
// {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the
// end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here
// to ensure any necessary pause logic occurs. In the case where the Activity will be
// shown regardless of the lock screen, the call to
// {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped.
final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
if (next == null || !next.canTurnScreenOn()) {
checkReadyForSleep();
}
} finally {
mInResumeTopActivity = false;
}
return result;
}
上面這段代碼中,resumeTopActivityUncheckedLocked又調用了resumeTopActivityInnerLocked,resumeTopActivityInnerLocked又調用了ActivityStackSupervisor的startSpecificActivityLocked,startSpecificActivityLocked的源碼如下所示:
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);
boolean knownToBeDead = false;
if (wpc != null && wpc.hasThread()) {
try {
realStartActivityLocked(r, wpc, 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.
knownToBeDead = true;
}
// Suppress transition until the new activity becomes ready, otherwise the keyguard can
// appear for a short amount of time before the new process with the new activity had the
// ability to set its showWhenLocked flags.
if (getKeyguardController().isKeyguardLocked()) {
r.notifyUnknownVisibilityLaunched();
}
try {
if (Trace.isTagEnabled(TRACE_TAG_ACTIVITY_MANAGER)) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dispatchingStartProcess:"
+ r.processName);
}
// Post message to start process to avoid possible deadlock of calling into AMS with the
// ATMS lock held.
final Message msg = PooledLambda.obtainMessage(
ActivityManagerInternal::startProcess, mService.mAmInternal, r.processName,
r.info.applicationInfo, knownToBeDead, "activity", r.intent.getComponent());
mService.mH.sendMessage(msg);
} finally {
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
}
最後又調用了realStartActivityLocked,我們來看下圖瞭解ActivityStack和ActivityStackSupervisor之間的互相傳遞過程
備註:下面的分析是基於Android9.0的代碼分析和書上的代碼有些差異。
在ActivityStackSupervisor.realStartActivityLocked方法中爲ClientTransaction對象添加LaunchActivityItem的callback,然後設置當前的生命週期狀態,最後調用ClientLifecycleManager.scheduleTransaction方法執行。
最終調用到ClientTransaction的schedule方法。
public void schedule() throws RemoteException {
mClient.scheduleTransaction(this);//private IApplicationThread mClient;
}
ClientTransaction.schedule方法的mClient是一個IApplicationThread類型,ActivityThread的內部類ApplicationThread派生這個接口類並實現了對應的方法。所以直接跳轉到ApplicationThread中的scheduleTransaction方法。ActivityThread類中並沒有定義scheduleTransaction方法,所以調用的是他父類ClientTransactionHandler的scheduleTransaction方法。
解析說明如下:
ApplicationThread的scheduleTransaction方法:
@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
ActivityThread.this.scheduleTransaction(transaction);//看到調用了ActivityThread的這個方法
//而ActivityThread沒有實現該方法,所以調用父類ClientTransactionHandler的這個方法。
//public final class ActivityThread extends ClientTransactionHandler {
}
ClientTransactionHandler的方法:(發送了一條消息給ActivityThread)
/** Prepare and schedule transaction for execution. */
void scheduleTransaction(ClientTransaction transaction) {
transaction.preExecute(this);
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
在ClientTransactionHandler.scheduleTransaction方法中調用了sendMessage方法,這個方法是一個抽象方法,其實現在ClientTransactionHandler派生類的ActivityThread中。
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);//定義:final H mH = new H();
}
ActivityThread.sendMessage方法會把消息發送給內部名字叫H的Handler。
看下H對EXECUTE_TRANSACTION處理方式:
case EXECUTE_TRANSACTION:
final ClientTransaction transaction = (ClientTransaction) msg.obj;
mTransactionExecutor.execute(transaction);//看到調用到了execute方法
if (isSystem()) {
// Client transactions inside system process are recycled on the client side
// instead of ClientLifecycleManager to avoid being cleared before this
// message is handled.
transaction.recycle();
}
// TODO(lifecycler): Recycle locally scheduled transactions.
break;
Handler H的實例接收到EXECUTE_TRANSACTION消息後調用TransactionExecutor.execute方法切換Activity狀態。TransactionExecutor.execute方法裏面先執行Callbacks,然後改變Activity當前的生命週期狀態。
frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
public void execute(ClientTransaction transaction) {
...
executeCallbacks(transaction);
executeLifecycleState(transaction);
...
}
public void executeCallbacks(ClientTransaction transaction) {
if (callbacks == null) {
// No callbacks to execute, return early.
return;
}
...
for (int i = 0; i < size; ++i) {
final ClientTransactionItem item = callbacks.get(i);
...
item.execute(mTransactionHandler, token, mPendingActions);//這個其實就是執行了我們定義的LaunchActivityItem裏面的execute方法。
item.postExecute(mTransactionHandler, token, mPendingActions);
...
}
}
/** Transition to the final state if requested by the transaction. */
private void executeLifecycleState(ClientTransaction transaction) {
...
// Cycle to the state right before the final requested state.
cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */);
// Execute the final transition with proper parameters.
lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
}
可以看到我們之前在AMS中設置了callback:
ClientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
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, proc.getReportedProcState(),
r.icicle, r.persistentState, results, newIntents,
dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
r.assistToken));
//clientTransaction的addCallback定義如下:
public void addCallback(ClientTransactionItem activityCallback) {
if (mActivityCallbacks == null) {
mActivityCallbacks = new ArrayList<>();
}
mActivityCallbacks.add(activityCallback);
}
執行callback後跳轉到LaunchActivityItem.execute方法。
frameworks/base/core/java/android/app/servertransaction/LaunchActivityItem.java
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
...
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
}
frameworks/base/core/java/android/app/ActivityThread.java
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
...
final Activity a = performLaunchActivity(r, customIntent);
...
return a;
}
可以看到我們最終執行到了ActivitityThread中的performLaunchActivity方法了。
========有個疑問,client.handleLaunchActivity(r, pendingActions, null /* customIntent */);怎麼就調到ActivityThread中的handleLaunchActivity方法呢?
//ActivitityThread中的mTransactionExecutor初始化
private final TransactionExecutor mTransactionExecutor = new TransactionExecutor(this);
//TransactionExecutor的構造
public TransactionExecutor(ClientTransactionHandler clientTransactionHandler) {
mTransactionHandler = clientTransactionHandler;
}
//這裏就可以看到mTransactionHandler 這個對象就是ActivityThread
//executeCallbacks方法中的代碼,將mTransactionHandler傳遞給了LaunchActivityItem.java中的execute方法。
item.execute(mTransactionHandler, token, mPendingActions);
所以這裏的client.handleLaunchActivity,就是調用的ActivityThread中的handleLaunchActivity方法。
========疑問已解答
到這裏我們的代碼就比較清晰了。看看performLaunchActivity這個方法主要完成的作用。
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對象
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.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,他的實現就比較簡單,就是通過類加載器創建
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
String pkg = intent != null && intent.getComponent() != null
? intent.getComponent().getPackageName() : null;
return getFactory(pkg).instantiateActivity(cl, className, intent);
}
3.通過LoadedApk的makeApplicatiton方法來創建Application對象
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
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);
}
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)) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
throw new RuntimeException(
"Unable to instantiate application " + appClass
+ ": " + e.toString(), e);
}
}
mActivityThread.mAllApplications.add(app);
mApplication = app;
if (instrumentation != null) {
try {
instrumentation.callApplicationOnCreate(app);//調用Application的onCreate的方法
} catch (Exception e) {
if (!instrumentation.onException(app, e)) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
}
...
return app;
}
4.創建ContextImpl對象並通過Activity的attach方法來完成一些重要數據的初始化
ContextImpl是一個很重要的數據結構,它是Context的具體實現,Context中的大部分邏輯都是ContextImpl來處理的。ContextImpl是通過Activity的attach方法和Activity建立關聯的,除此之外,在attach方法中Activity還會完成Window的創建並且建立自己和Window的關聯。這樣當Window接收到外部輸入的事件後就可以將事件傳遞給Activity。
5.調用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()");
}
mInstrumentation.callActivityOnCreate(activity, r.state);,由於Activity的onCreate已經被調用,這也意味着Activity完成了整個啓動過程。
到這裏Activity的啓動過程就分析完成了。我是在Android9.0的源碼下查閱的。和書上的代碼有些差異。但是分析的流程都類似。
總結:整體的啓動大概就是app發起一個啓動activity的請求,通過Binder的IPC過程將啓動交給AMS來處理。AMS中經過多重方法的調用,數據處理。最終也會通過Binder的IPC來回調到週期函數。初始化數據。最終完成整個流程的啓動。