Activity框架和管理結構
Activity管理的核心是AcitivityManagerService,是一個獨立的進程;
ActiveThread是每一個應用程序所在進程的主線程,循環的消息處理;
ActiveThread與AcitivityManagerService的通信是屬於進程間通信,使用binder機制,通過ApplicationThread這個橋樑進行通信
ApplicationThread是ActivityThread的一個內部類
一個應用程序中所有Activity只有一個ActivityThread屬於一個Process
ActiveThread重要成員介紹:
final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();//activity記錄類
final ApplicationThread mAppThread = new ApplicationThread();用來與AMS交互通信的橋樑,是一個binder.
final H mH = new H();消息循環handler。
Instrumentation mInstrumentation;用於監控程序和系統之間的交互操作
ActivityManagerService:Activity管理服務類,通過mHistory棧來管理所有的activity,應用啓動activity之後,發動啓動請求到AMS,AMS會根據
activity、ProcessRecord等信息創建HistoryRecord實例r並加入到mHistory當中。activity被加入到mHistory之後,只是說明在服務端可以找到該
activity記錄了,但是在客戶端目前還沒有該activity記錄。還需要通過ProcessRecord中的thread(IApplication)變量,調用它的
scheduleLaunchActivity方法在ActivityThread中創建新的ActivityRecord記錄(之前我們說過,客戶端的activity是用ActivityRecord
記錄的,並放在mActivities中)
app.thread.scheduleLaunchActivity(new Intent(r.intent), r,System.identityHashCode(r),
ActivityRecord:activity記錄類,代表一個Activity。
TaskRecord:任務棧記錄類,代表一個存放activity的任務棧
ActivityStarter:activity啓動前邏輯處理類,主要收集所有的邏輯來確定意圖(intent)和標誌(flag),然後轉變爲對應的活動(activity)和關聯的任務和堆棧
ActivityStack:activtiy任務棧管理類,維護着一個private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();負責管理各個activity的任務棧
ActivityStackSupervisor:任務棧超級管理員,其實算ActivityStack的輔助管理類,它和ActivityStack相互持有
系統啓動的時候,會創建一個PackageManagerService,PackageManagerService會對應用程序的配置文件AndroidManifest.xml進行解析,從而得到程序裏的組件信息。
PackageManagerService去查詢所有action爲“android.intent.action.MAIN”並且category爲“android.intent.category.LAUNCHER”的Activity,然後爲每個
應用程序創建一個快捷方式圖標,並把程序信息與之關聯,作爲啓動的第一個Activity。
我將activty啓動分爲以下幾步:
1、客戶端發出啓動activity命令;
2、AMS接受到命令,啓動Activity相關工作
3、AMS查詢當前需要啓動activity的任務棧是否有需要執行onPasue的activity,如果有執行,如果沒有啓動activity
4、如果有需要執行onPause的activity,那麼回調客戶端調用該方法
5、該方法調用完成後,通知AMS啓動需要啓動的activity
6、需要啓動的activity準備信息完成後,判斷該activity所屬進程是否已經啓動,如果啓動,直接啓動activity,如果沒有,先啓動進程,進入到該進程的activityThread的main方法
7、AMS啓動activity,通知客戶端,調用app.thread.scheduleLaunchActivity
8、客戶端執行scheduleLaunchActivity,進行activity的一系列啓動動作:生命週期方法執行、設置視圖、通知WMS繪製視圖
9、activity成功啓動後,通知AMS讓需要執行onStop方法的activity執行該方法
其中1-7步主要在AMS部分執行
第8步在客戶端執行
第9步在AMS執行
AMS部分:
1、不管是從lancher啓動還是應用內啓動,最原始的起點,都是activity內部的startActivity方法
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
startActivityForResult(intent, -1);
}
}
參數requestCode=-1表示不需要把結果傳送回來。
然後進入到Instrumentation的execStartActivity方法,然後會調用
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
進入到AMS中的startActivity方法中
2、AMS中的startActivity的方法線
startActivity->startActivityAsUser->mActivityStarter.startActivityMayWait
3、進入到ActivityStarter,對Intent進行分析處理
startActivityMayWait->startActivityLocked->startActivityUnchecked->ActivityStack.startActivityLocked->ActivityStackSupervisor.resumeFocusedStackTopActivityLocked
在Starter的startActivityLocked方法中,有一個非常重要的地方,就是創建了一個ActivityRecord,表示一個Activity的所有信息
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
options, sourceRecord);
在這個ActivityRecoder中,我們有一點要記住,它創建了一個 appToken = new Token(this, service);
它是一個static class Token extends IApplicationToken.Stub,代表着這個Activity,這個Token最終是和WMS交互的身份校驗符
接下來進入startActivityUnchecked方法,這裏主要做一些啓動前的任務棧、Activity狀態的初始化工作,
然後進入到ActivityStack.startActivityLocked將token傳遞給WMS
最後進入到ActivityStackSupervisor.resumeFocusedStackTopActivityLocked方法
4、進入到ActivityStack的startActivityLocked方法,將剛剛生成的token傳遞給WMS
startActivityLocked->addConfigOverride->mWindowManager.addAppToken(......);
5、進入到ActivityStackSupervisor.resumeFocusedStackTopActivityLocked
resumeFocusedStackTopActivityLocked->ActivityStack.resumeTopActivityUncheckedLocked->ActivityStack.resumeTopActivityInnerLocked
resumeTopActivityInnerLocked這個方法是啓動前的最終檢查,這裏會有一個判斷:
if (mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Pausing " + mResumedActivity);
pausing |= startPausingLocked(userLeaving, false, next, dontWaitForPause);
}
if (pausing) {
if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
"resumeTopActivityLocked: Skip resume: need to start pausing");
// At this point we want to put the upcoming activity's process
// at the top of the LRU list, since we know we will be needing it
// very soon and it would be a waste to let it get killed if it
// happens to be sitting towards the end.
if (next.app != null && next.app.thread != null) {
mService.updateLruProcessLocked(next.app, true, null);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
如果任務棧頂的Activity不爲null,那麼執行上一個activity的onPasuse方法,然後返回,該方法到此爲止
如果沒有執行onPause方法的activity,又會進行下一個判斷:
if (next.app != null && next.app.thread != null) {
......
}else{
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
這裏很好理解,如果要啓動的activity已經創建過了,那麼再次把它放到棧頂,會執行onRestart方法然後走對應的生命週期
如果沒有那麼進入到mStackSupervisor.startSpecificActivityLocked方法來創建一個新的activity。這裏我們先不分析,我們先分析onPause這條線,最後也會走到mStackSupervisor.startSpecificActivityLocked這裏來的
6、進入到ActivityStack.startPausingLocked方法
首先會執行completePauseLocked
在ActivityStack.completePauseLocked的方法中,有一個判斷當上一個activity不可見了,是pause狀態,那麼執行addToStopping方法
if (!mStackSupervisor.mStoppingActivities.contains(r)) {
mStackSupervisor.mStoppingActivities.add(r);
}
將該activity加入到mStoppingActivities集合中,等待調用onStop方法
if (prev.app != null && prev.app.thread != null) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
try {
EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
prev.userId, System.identityHashCode(prev),
prev.shortComponentName);
mService.updateUsageStats(prev, false);
prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
userLeaving, prev.configChangeFlags, dontWait);
} catch (Exception e) {
// Ignore exception, if process died other code will cleanup.
Slog.w(TAG, "Exception thrown during pause", e);
mPausingActivity = null;
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
}
這裏可以看出,如果棧頂activity確實存在,並且進程沒有死掉,那麼會回調它的schedulePauseActivity方法,至此,我們回到客戶端的ActivityThread.ApplicationThread中
7、ApplicationThread.schedulePauseActivity方法
發送了一個PAUSE_ACTIVITY的message,然後進入到handlePauseActivity方法
handlePauseActivity->performPauseActivity->performPauseActivityIfNeeded->mInstrumentation.callActivityOnPause(r.activity)->activity.performPause();
至此,上一個activity的onPause方法執行
if (!dontReport) {
try {
ActivityManagerNative.getDefault().activityPaused(token);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
至此,我們又回到了AMS中的activityPaused方法
8、AMS的activityPaused方法
activityPaused->ActivityStack.activityPausedLocked->ActivityStack.completePauseLocked
然後又調用了mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
我們又進入到了ActivityStackSupervisor.resumeFocusedStackTopActivityLocked的方法,
9、又進入到ActivityStackSupervisor.resumeFocusedStackTopActivityLocked
resumeFocusedStackTopActivityLocked->ActivityStack.resumeTopActivityUncheckedLocked->ActivityStack.resumeTopActivityInnerLocked
再次進入該方法後,之前的pause方法那裏會跳過,會根據獲取到的棧頂activity next的狀態來判斷:
如果沒有執行onPause方法的activity,又會進行下一個判斷:
if (next.app != null && next.app.thread != null) {
......
}else{
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
這裏很好理解,如果要啓動的activity已經創建過了,那麼再次把它放到棧頂,會執行onRestart方法然後走對應的生命週期
如果沒有那麼進入到mStackSupervisor.startSpecificActivityLocked方法來創建一個新的activity。
所以,接下來進入到mStackSupervisor.startSpecificActivityLocked方法
10、進入到startSpecificActivityLocked方法
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
首先獲取到該activity所屬的進程,判斷該activity的進程是否已經啓動,如果已經啓動進入startSpecificActivityLocked方法回調客戶端的app.thread.scheduleLaunchActivity方法
如果該activity的進程沒有啓動,那麼啓動進程
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
我們這裏重點分析啓動進程的這一塊,因爲這一塊最後也會進入到app.thread.scheduleLaunchActivity方法
11、啓動進程後,會執行客戶端的ActivityThread的main方法。
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
Looper.loop();
在Main方法中,開啓UI線程消息隊列循環,新建ActivityThread對象,執行ActivityThread的attach方法
attach函數主要通過binder機制與AMS進行通信,它主要做了:
將ApplicationThread與ActivityManager進行綁定
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
通過調用AMS的代理attachApplication方法來實現。這樣在AMS中建立了app進程ProcessRecord的信息,通過這個ProcessRecord就可以回調
ApplicationThread中的方法來啓動app進程中的activity。
11、在AMS中,先調用了attachApplication方法,
attachApplication->attachApplicationLocked->mStackSupervisor.attachApplicationLocked
在attachApplicationLocked方法中,進行了application的綁定:thread.bindApplication(......)
handleBindApplication方法裏面做了兩件事:
1、創建Instrumentation
2、在LoadedApk中創建Application app = data.info.makeApplication(data.restrictedBackupMode, null);在ActivityThread中賦值給mInitialApplication;
我們來看makeApplication方法:
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);
創建ContextImpl並賦值給Application,這個ContextImpl就是Application的mBase變量,也就是getBaseContext所獲取的值,在Context專題中會講到,在Activity也會遇到它
不管是Activity還是Application中去調用getApplicationContext,最後都會調用
@Override
public Context getApplicationContext() {
return (mPackageInfo != null) ?
mPackageInfo.getApplication() : mMainThread.getApplication();
}
mPackageInfo.getApplication()或者mMainThread.getApplication()都指向剛剛創建的application
然後調用了mStackSupervisor.attachApplicationLocked(app)方法。在該方法中會調用realStartActivityLocked(hr, app, true, true)方法。
在該方法中又會調用app.thread.scheduleLaunchActivity方法回到activityThread中啓動activity。
客戶端部分:
12、scheduleLaunchActivity->handleLaunchActivity->performLaunchActivity->handleResumeActivity
在scheduleLaunchActivity方法裏面會創建一個ActivityClientRecord r = new ActivityClientRecord();對象它對應着AMS的ActivityRecord
在與AMS綁定了之後,AMS會最終會調用ApplicationThread的scheduleLaunchActivity方法,該方法會用H發送一個 sendMessage(H.LAUNCH_ACTIVITY, r);消息
在H中,接受到消息之後,會調用 handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");方法
首先調用performLaunchActivity生成Activity實例,並對其參數進行初始化,這裏包括
1、創建activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
2、如果application沒有創建或者啓動,創建
3、創建ContextImpl Context appContext = createBaseContextForActivity(r, activity);
4、執行activity.attach方法,設定mBase爲剛剛創建的ContextImpl,創建mWindow = new PhoneWindow(this, window);設定window的回調爲自身,設定window的windowManager
5、執行聲明週期函數onCreate,mInstrumentation.callActivityOnCreate,執行onStart方法activity.performStart();
最後將activity存放到集合中,mActivities.put(r.token, r);
接下來進入handleResumeActivity方法
首先執行performResumeActivity方法,執行activity的onResume方法 r.activity.performResume();
執行完相關生命週期函數之後,handleResumeActivity方法裏開始進行窗口綁定,將activity顯示到窗口上。
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (r.mPreserveWindow) {
a.mWindowAdded = true;
r.mPreserveWindow = false;
// Normally the ViewRoot sets up callbacks with the Activity
// in addView->ViewRootImpl#setView. If we are instead reusing
// the decor view we have to notify the view root that the
// callbacks may have changed.
ViewRootImpl impl = decor.getViewRootImpl();
if (impl != null) {
impl.notifyChildRebuilt();
}
}
if (a.mVisibleFromClient && !a.mWindowAdded) {
a.mWindowAdded = true;
wm.addView(decor, l);
}
13、當activity成功啓動,並且執行完生命週期函數後,繼續通知AMS執行之前activity的onStop方法
Looper.myQueue().addIdleHandler(new Idler());
在最後會往消息隊列裏面傳遞一個閒時任務,這個任務會調用AMS的方法
am.activityIdle(a.token, a.createdConfig, stopProfiling);
activityIdle->mStackSupervisor.activityIdleInternalLocked->stack.stopActivityLocked
ActivityRecord r =mStackSupervisor.activityIdleInternalLocked(token, false, config);
for (int i = 0; i < NS; i++) {
r = stops.get(i);
final ActivityStack stack = r.task.stack;
if (stack != null) {
if (r.finishing) {
stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
} else {
stack.stopActivityLocked(r);
}
}
}
如果是銷燬掉的activity,執行finishCurrentActivityLocked,如果只是執行onStop方法,執行stopActivityLocked
在stopActivityLocked方法裏面我們可以看到r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags);
最終就執行了onStop方法