Android Activity startActivity流程簡介
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
1. 基本概念
1.1 Instrumentation是什麼?
顧名思義,儀器儀表,用於在應用程式中進行“測量”和“管理”工作。一個應用程式中只有一個
當ActivityThread 建立(callActivityOnCreate)、暫停、恢復某個Activity時,通過呼叫此物件的方法來實現,如:
1) 建立: callActivityOnCreate
2) 暫停: callActivityOnPause
3) 恢復: callActivityOnResume
Instrumentation和ActivityThread的關係,類似於老闆與經理的關係,老闆負責對外交流(如與Activity Manager Service<AMS>),Instrumentation負責管理並完成老闆交待的任務。
它通過以下兩個成員變數來對當前應用程序中的Activity進行管理:
private List<ActivityWaiter> mWaitingActivities; private List<ActivityMonitor> mActivityMonitors;
其功能函式下表所示:
功能 | 函式 |
增加刪除Monitor | addMonitor(ActivityMonitor monitor) removeMonitor(ActivityMonitor monitor) |
Application與Activity生命週期控制 | newApplication(Class<?> clazz, Context context) newActivity(ClassLoader cl, String className,Intent intent) callActivityOnCreate(Activity activity, Bundle icicle) callActivityOnDestroy(Activity activity) callActivityOnStart(Activity activity) callActivityOnRestart(Activity activity) callActivityOnResume(Activity activity) callActivityOnStop(Activity activity) callActivityOnPause(Activity activity) |
Instrumentation生命週期控制 | onCreate(Bundle arguments) start() onStart() finish(int resultCode, Bundle results) onDestroy() |
傳送使用者操控資訊到當前視窗 | sendCharacterSync(int keyCode) sendPointerSync(MotionEvent event) sendTrackballEventSync(MotionEvent event) sendTrackballEventSync(MotionEvent event) |
同步操作 | startActivitySync(Intent intent) //它呼叫Context.startActivity runOnMainSync(Runnable runner) waitForIdle() |
2. Android應用程式啟動過程(MainActivity)
即MainActivity的啟動過程,在此過程中,將建立一個新的程序來執行此MainActivity。
Android應用程式從Launcher啟動流程如下所示:
/***************************************************************** * Launcher通過Binder告訴ActivityManagerService, * 它將要啟動一個新的Activity; ****************************************************************/Launcher.startActivitySafely-> Launcher.startActivity-> //要求在新的Task中啟動此Activity //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) Activity.startActivity-> Activity.startActivityForResult-> Instrumentation.execStartActivity-> // ActivityManagerNative.getDefault()返回AMS Proxy介面 ActivityManagerNative.getDefault().startActivity-> ActivityManagerProxy.startActivity-> ActivityManagerService.startActivity-> (AMS) ActivityManagerService.startActivityAsUser-> ActivityStack.startActivityMayWait-> ActivityStack.resolveActivity(獲取ActivityInfo) //aInfo.name為main Activity,如:com.my.test.MainActivity //aInfo.applicationInfo.packageName為包名,如com.my.test ActivityStack.startActivityLocked-> //ProcessRecord callerApp; 呼叫者即Launcher資訊 //ActivityRecord sourceRecord; Launcher Activity相關資訊 //ActivityRecord r=new ActivityRecord(...),將要建立的Activity相關資訊 ActivityStack.startActivityUncheckedLocked-> //Activity啟動方式:ActivityInfo.LAUNCH_MULTIPLE/LAUNCH_SINGLE_INSTANCE/ // ActivityInfo.LAUNCH_SINGLE_TASK/LAUNCH_SINGLE_TOP) // 建立一個新的task,即TaskRecord,並儲存在ActivityRecord.task中 //r.setTask(new TaskRecord(mService.mCurTask, r.info, intent), null, true) // 把新建立的Activity放在棧頂 ActivityStack.startActivityLocked-> ActivityStack.resumeTopActivityLocked-> ActivityStack.startPausingLocked (使Launcher進入Paused狀態)-> /***************************************************************** * AMS通過Binder通知Launcher進入Paused狀態 ****************************************************************/ ApplicationThreadProxy.schedulePauseActivity-> //private class ApplicationThread extends ApplicationThreadNative ApplicationThread.schedulePauseActivity-> ActivityThread.queueOrSendMessage-> // 呼叫Activity.onUserLeaveHint // 呼叫Activity.onPause // 通知activity manager我進入了pause狀態 ActivityThread.handlePauseActivity-> /***************************************************************** * Launcher通過Binder告訴AMS,它已經進入Paused狀態 ****************************************************************/ ActivityManagerProxy.activityPaused-> ActivityManagerService.activityPaused-> ActivityStack.activityPaused->(把Activity狀態修改為PAUSED) ActivityStack.completePauseLocked-> // 引數為代表Launcher這個Activity的ActivityRecord // 使用棧頂的Activity進入RESUME狀態 ActivityStack.resumeTopActivityLokced-> //topRunningActivityLocked將剛建立的放於棧頂的activity取回來 // 即在ActivityStack.startActivityUncheckedLocked中建立的 /***************************************************************** * AMS建立一個新的程序,用來啟動一個ActivityThread例項, * 即將要啟動的Activity就是在這個ActivityThread例項中執行 ****************************************************************/ ActivityStack.startSpecificActivityLocked-> // 建立對應的ProcessRecord ActivityManagerService.startProcessLocked-> // 啟動一個新的程序 // 新的程序會匯入android.app.ActivityThread類,並且執行它的main函式, // 即例項化ActivityThread, 每個應用有且僅有一個ActivityThread例項 Process.start("android.app.ActivityThread",...)-> // 通過zygote機制建立一個新的程序 Process.startViaZygote-> // 這個函式在程序中建立一個ActivityThread例項,然後呼叫 // 它的attach函式,接著就進入訊息迴圈 ActivityThread.main-> /***************************************************************** * ActivityThread通過Binder將一個ApplicationThread類的Binder物件 * 傳遞給AMS,以便AMS通過此Binder物件來控制Activity整個生命週期 ****************************************************************/ ActivityThread.attach-> IActivityManager.attachApplication(mAppThread)-> ActivityManagerProxy.attachApplication-> ActivityManagerService.attachApplication-> // 把在ActivityManagerService.startProcessLocked中建立的ProcessRecord取出來 ActivityManagerService.attachApplicationLocked-> /***************************************************************** * AMS通過Binder通知ActivityThread一切準備OK,它可以真正啟動新的Activity了 ****************************************************************/ // 真正啟動Activity ActivityStack.realStartActivityLocked-> ApplicationThreadProxy.scheduleLaunchActivity-> ApplicationThread.scheduleLaunchActivity-> ActivityThread.handleLaunchActivity-> // 載入新的Activity類,並執行它的onCreate ActivityThread.performLaunchActivity /*1) Instrumentation.newActivity: 載入新類,即建立Activity物件; 2) ActivityClientRecord.packageInfo.makeApplication:建立Application物件; <LoadedApk.makeApplication> 3) Activity.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):把Application attach到Activity, 即把Activtiy 相關資訊設定到新建立的Activity中 4) Instrumentation.callActivityOnCreate:呼叫onCreate;*/ // 使用Activity進入RESUMED狀態,並呼叫onResume ActivityThread.handleResumeActivity
3. ActivityManagerService
3.1 類中關鍵資訊
public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback { ... // Maximum number of recent tasks that we can remember. static final int MAX_RECENT_TASKS = 20; public ActivityStack mMainStack; // 管理Activity堆疊 // Whether we should show our dialogs (ANR, crash, etc) or just perform their // default actuion automatically. Important for devices without direct input // devices. private boolean mShowDialogs = true; /** * Description of a request to start a new activity, which has been held * due to app switches being disabled. */ static class PendingActivityLaunch { ActivityRecord r; ActivityRecord sourceRecord; int startFlags; } /** * Activity we have told the window manager to have key focus. */ ActivityRecord mFocusedActivity = null; /** * List of intents that were used to start the most recent tasks. */ final ArrayList<TaskRecord> mRecentTasks = new ArrayList<TaskRecord>(); /** * Process management. */ final ProcessList mProcessList = new ProcessList(); /** * All of the applications we currently have running organized by name. * The keys are strings of the application package name (as * returned by the package manager), and the keys are ApplicationRecord * objects. */ final ProcessMap<ProcessRecord> mProcessNames = new ProcessMap<ProcessRecord>(); /** * The currently running isolated processes. */ final SparseArray<ProcessRecord> mIsolatedProcesses = new SparseArray<ProcessRecord>(); ... public static final Context main(int factoryTest) { //main入口函式 AThread thr = new AThread(); thr.start(); synchronized (thr) { while (thr.mService == null) { try { thr.wait(); } catch (InterruptedException e) { } } } ActivityManagerService m = thr.mService; mSelf = m; ActivityThread at = ActivityThread.systemMain(); mSystemThread = at; Context context = at.getSystemContext(); context.setTheme(android.R.style.Theme_Holo); m.mContext = context; m.mFactoryTest = factoryTest; m.mMainStack = new ActivityStack(m, context, true); // 建立ActivityStack m.mBatteryStatsService.publish(context); m.mUsageStatsService.publish(context); synchronized (thr) { thr.mReady = true; thr.notifyAll(); } m.startRunning(null, null, null, null); return context; }}
3.2 家族圖譜
4. ActivityStack-真正做事的傢伙
ActivityManagerService使用它來管理系統中所有的Activities的狀態,Activities使用stack的方式進行管理。它是真正負責做事的傢伙,很勤快的,但外界無人知道!
4.1 類中關鍵資訊
/** * State and management of a single stack of activities. */final class ActivityStack { final ActivityManagerService mService; final boolean mMainStack; final Context mContext; enum ActivityState { INITIALIZING, RESUMED, PAUSING, PAUSED, STOPPING, STOPPED, FINISHING, DESTROYING, DESTROYED } /** * The back history of all previous (and possibly still * running) activities. It contains HistoryRecord objects. */ final ArrayList<ActivityRecord> mHistory = new ArrayList<ActivityRecord>(); /** * Used for validating app tokens with window manager. */ final ArrayList<IBinder> mValidateAppTokens = new ArrayList<IBinder>(); /** * List of running activities, sorted by recent usage. * The first entry in the list is the least recently used. * It contains HistoryRecord objects. */ final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<ActivityRecord>(); /** * List of activities that are waiting for a new activity * to become visible before completing whatever operation they are * supposed to do. */ final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<ActivityRecord>(); /** * List of activities that are ready to be stopped, but waiting * for the next activity to settle down before doing so. It contains * HistoryRecord objects. */ final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<ActivityRecord>(); /** * List of activities that are in the process of going to sleep. */ final ArrayList<ActivityRecord> mGoingToSleepActivities = new ArrayList<ActivityRecord>(); /** * When we are in the process of pausing an activity, before starting the * next one, this variable holds the activity that is currently being paused. */ ActivityRecord mPausingActivity = null; /** * This is the last activity that we put into the paused state. This is * used to determine if we need to do an activity transition while sleeping, * when we normally hold the top activity paused. */ ActivityRecord mLastPausedActivity = null; /** * Current activity that is resumed, or null if there is none. */ ActivityRecord mResumedActivity = null; /** * This is the last activity that has been started. It is only used to * identify when multiple activities are started at once so that the user * can be warned they may not be in the activity they think they are. */ ActivityRecord mLastStartedActivity = null; /** * Set to indicate whether to issue an onUserLeaving callback when a * newly launched activity is being brought in front of us. */ boolean mUserLeaving = false; ActivityStack(ActivityManagerService service, Context context, boolean mainStack) { mService = service; mContext = context; mMainStack = mainStack; ... } ...}
4.2 家族圖譜
5. ProcessRecord
記錄了一個程序的相關資訊。
5.1 類中關鍵資訊
/** * Full information about a particular process that * is currently running. */class ProcessRecord { final ApplicationInfo info; // all about the first app in the process final boolean isolated; // true if this is a special isolated process final int uid; // uid of process; may be different from 'info' if isolated final int userId; // user of process. final String processName; // name of the process IApplicationThread thread; // the actual proc... may be null only if // 'persistent' is true (in which case we // are in the process of launching the app) // 是ApplicationThread物件的遠端介面, // 通過此介面通知Activity進入對應的狀態 int pid; // The process of this application; 0 if none ApplicationInfo instrumentationInfo; // the application being instrumented BroadcastRecord curReceiver;// receiver currently running in the app // contains HistoryRecord objects final ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(); // all ServiceRecord running in this process final HashSet<ServiceRecord> services = new HashSet<ServiceRecord>(); // services that are currently executing code (need to remain foreground). final HashSet<ServiceRecord> executingServices = new HashSet<ServiceRecord>(); // All ConnectionRecord this process holds final HashSet<ConnectionRecord> connections = new HashSet<ConnectionRecord>(); // all IIntentReceivers that are registered from this process. final HashSet<ReceiverList> receivers = new HashSet<ReceiverList>(); // class (String) -> ContentProviderRecord final HashMap<String, ContentProviderRecord> pubProviders = new HashMap<String, ContentProviderRecord>(); // All ContentProviderRecord process is using final ArrayList<ContentProviderConnection> conProviders = new ArrayList<ContentProviderConnection>(); boolean persistent; // always keep this application running? boolean crashing; // are we in the process of crashing? Dialog crashDialog; // dialog being displayed due to crash. boolean notResponding; // does the app have a not responding dialog? Dialog anrDialog; // dialog being displayed due to app not resp. boolean removed; // has app package been removed from device? boolean debugging; // was app launched for debugging? boolean waitedForDebugger; // has process show wait for debugger dialog? Dialog waitDialog; // current wait for debugger dialog ProcessRecord(BatteryStatsImpl.Uid.Proc _batteryStats, IApplicationThread _thread, ApplicationInfo _info, String _processName, int _uid) { batteryStats = _batteryStats; info = _info; isolated = _info.uid != _uid; uid = _uid; userId = UserHandle.getUserId(_uid); processName = _processName; pkgList.add(_info.packageName); thread = _thread; maxAdj = ProcessList.HIDDEN_APP_MAX_ADJ; hiddenAdj = clientHiddenAdj = emptyAdj = ProcessList.HIDDEN_APP_MIN_ADJ; curRawAdj = setRawAdj = -100; curAdj = setAdj = -100; persistent = false; removed = false; } ...}
5. 2 家族圖譜
6. IApplicationThread介面AMS->Application
IApplicationThread為AMS作為客戶端訪問Application伺服器端的Binder介面。當建立Application時,將把此Binder物件傳遞給AMS,然後AMS把它儲存在mProcessNames.ProcessRecord.thread中。當需要通知Application工作時,則呼叫IApplicationThread中對應的介面函式。
其相互關係如下圖所示:
給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow
你好! 這是你第一次使用 **Markdown編輯器** 所展示的歡迎頁。如果你想學習如何使用Markdown編輯器, 可以仔細閱讀這篇文章,瞭解一下Markdown的基本語法知識。新的改變
我們對Markdown編輯器進行了一些功能拓展與語法支援,除了標準的Markdown編輯器功能,我們增加了如下幾點新功能,幫助你用它寫部落格:
- 全新的介面設計 ,將會帶來全新的寫作體驗;
- 在創作中心設定你喜愛的程式碼高亮樣式,Markdown 將程式碼片顯示選擇的高亮樣式 進行展示;
- 增加了 圖片拖拽 功能,你可以將本地的圖片直接拖拽到編輯區域直接展示;
- 全新的 KaTeX數學公式 語法;
- 增加了支援甘特圖的mermaid語法1 功能;
- 增加了 多螢幕編輯 Markdown文章功能;
- 增加了 焦點寫作模式、預覽模式、簡潔寫作模式、左右區域同步滾輪設定 等功能,功能按鈕位於編輯區域與預覽區域中間;
- 增加了 檢查列表 功能。
功能快捷鍵
撤銷:Ctrl/Command + Z
重做:Ctrl/Command + Y
加粗:Ctrl/Command + B
斜體:Ctrl/Command + I
標題:Ctrl/Command + Shift + H
無序列表:Ctrl/Command + Shift + U
有序列表:Ctrl/Command + Shift + O
檢查列表:Ctrl/Command + Shift + C
插入程式碼:Ctrl/Command + Shift + K
插入連結:Ctrl/Command + Shift + L
插入圖片:Ctrl/Command + Shift + G
合理的建立標題,有助於目錄的生成
直接輸入1次#,並按下space後,將生成1級標題。
輸入2次#,並按下space後,將生成2級標題。
以此類推,我們支援6級標題。有助於使用TOC
語法後生成一個完美的目錄。
如何改變文字的樣式
強調文字 強調文字
加粗文字 加粗文字
標記文字
刪除文字
引用文字
H2O is是液體。
210 運算結果是 1024.
插入連結與圖片
連結: link.
圖片:
帶尺寸的圖片:
當然,我們為了讓使用者更加便捷,我們增加了圖片拖拽功能。
如何插入一段漂亮的程式碼片
去部落格設定頁面,選擇一款你喜歡的程式碼片高亮樣式,下面展示同樣高亮的 程式碼片
.
// An highlighted block var foo = 'bar';
生成一個適合你的列表
- 專案
- 專案
- 專案
- 專案
- 專案1
- 專案2
- 專案3
- 計劃任務
- 完成任務
建立一個表格
一個簡單的表格是這麼建立的:
專案 | Value |
---|---|
電腦 | $1600 |
手機 | $12 |
導管 | $1 |
設定內容居中、居左、居右
使用:---------:
居中
使用:----------
居左
使用----------:
居右
第一列 | 第二列 | 第三列 |
---|---|---|
第一列文字居中 | 第二列文字居右 | 第三列文字居左 |
SmartyPants
SmartyPants將ASCII標點字元轉換為“智慧”印刷標點HTML實體。例如:
TYPE | ASCII | HTML |
---|---|---|
Single backticks | 'Isn't this fun?' |
‘Isn’t this fun?’ |
Quotes | "Isn't this fun?" |
“Isn’t this fun?” |
Dashes | -- is en-dash, --- is em-dash |
– is en-dash, — is em-dash |
建立一個自定義列表
- Markdown
- Text-to- HTML conversion tool
- Authors
- John
- Luke
如何建立一個註腳
一個具有註腳的文字。2
註釋也是必不可少的
Markdown將文字轉換為 HTML。
KaTeX數學公式
您可以使用渲染LaTeX數學表示式 KaTeX:
Gamma公式展示 是通過尤拉積分
你可以找到更多關於的資訊 LaTeX 數學表示式here.
新的甘特圖功能,豐富你的文章
gantt
dateFormat YYYY-MM-DD
title Adding GANTT diagram functionality to mermaid
section 現有任務
已完成 :done, des1, 2014-01-06,2014-01-08
進行中 :active, des2, 2014-01-09, 3d
計劃一 : des3, after des2, 5d
計劃二 : des4, after des3, 5d
- 關於 甘特圖 語法,參考 這兒,
UML 圖表
可以使用UML圖表進行渲染。 Mermaid. 例如下面產生的一個序列圖::
這將產生一個流程圖。:
- 關於 Mermaid 語法,參考 這兒,
FLowchart流程圖
我們依舊會支援flowchart的流程圖:
- 關於 Flowchart流程圖 語法,參考 這兒.
匯出與匯入
匯出
如果你想嘗試使用此編輯器, 你可以在此篇文章任意編輯。當你完成了一篇文章的寫作, 在上方工具欄找到 文章匯出 ,生成一個.md檔案或者.html檔案進行本地儲存。
匯入
如果你想載入一篇你寫過的.md檔案或者.html檔案,在上方工具欄可以選擇匯入功能進行對應副檔名的檔案匯入,
繼續你的創作。
註腳的解釋 ↩︎