startActivityAndWait函數有很多參數,先來認識一下它們。
**ActiivtyManagerService.java::startActivityAndWait原型**
~~~
publicfinal WaitResult startActivityAndWait(
/*
在絕大多數情況下,一個Acitivity的啟動是由一個應用進程發起的,IApplicationThread是
應用進程和AMS交互的通道,也可算是調用進程的標示,在本例中,AM并非一個應用進程,所以
傳遞的caller為null
*/
IApplicationThread caller,
//Intent及resolvedType,在本例中,resolvedType為null
Intentintent, String resolvedType,
//下面兩個參數和授權有關,讀者可參考第3章對CopyboardService分析中介紹的授權知識
Uri[] grantedUriPermissions,//在本例中為null
intgrantedMode,//在本例中為0
IBinder resultTo,//在本例中為null,用于接收startActivityForResult的結果
StringresultWho,//在本例中為null
//在本例中為0,該值的具體意義由調用者解釋。如果該值大于等于0,則AMS內部保存該值,
//并通過onActivityResult返回給調用者
int requestCode,
boolean onlyIfNeeded,//本例為false
boolean debug,//是否調試目標進程
//下面3個參數和性能統計有關
StringprofileFile,
ParcelFileDescriptor profileFd, booleanautoStopProfiler)
~~~
關于以上代碼中一些參數的具體作用,以后碰到時會再作分析。建議讀者先閱讀SDK文檔中關于Activity類定義的幾個函數,如startActivity、startActivityForResult及onActivityResult等。
startActivityAndWait的代碼如下:
**ActivityManagerService.java::startActivityAndWait**
~~~
publicfinal WaitResult startActivityAndWait(IApplicationThread caller,
Intent intent, String resolvedType, Uri[]grantedUriPermissions,
int grantedMode, IBinder resultTo,StringresultWho, int requestCode,
booleanonlyIfNeeded, boolean debug,String profileFile,
ParcelFileDescriptor profileFd, booleanautoStopProfiler) {
//創建WaitResult對象用于存儲處理結果
WaitResult res = new WaitResult();
//mMainStack為ActivityStack類型,調用它的startActivityMayWait函數
mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
grantedUriPermissions, grantedMode, resultTo, resultWho,
requestCode, onlyIfNeeded, debug, profileFile, profileFd,
autoStopProfiler, res, null);//最后一個參數為Configuration,
//在本例中為null
returnres;
}
~~~
mMainStack為AMS的成員變量,類型為ActivityStack,該類是Activity調度的核心角色。正式分析它之前,有必要先介紹一下相關的基礎知識。
1. Task、Back Stack、ActivityStack及Launch mode
(1) 關于Task及Back Stack的介紹
先來看圖6-10。
:-: 
圖6-10 用戶想干什么
圖6-10列出了用戶在Android系統上想干的三件事情,分別用A、B、C表示,將每一件事情稱為一個Task。一個Task還可細分為多個子步驟,即Activity。
* * * * *
**提示**:為什么叫Activity?讀者可參考Merrian-Webster詞典對Activity的解釋[^①]:“an organizational unit forperforming a specific function”,也就是說,它是一個有組織的單元,用于完成某項指定功能。
* * * * *
由圖6-10可知,A、B兩個Task使用了不同的Activity來完成相應的任務。注意,A、B這兩個Task的Activity之間沒有復用。
再來看C這個Task,它可細分為4個Activity,其中有兩個Activity分別使用了A Task的A1、B Task的B2。C Task為什么不新建自己的Activity,反而要用其他Task的呢?這是因為用戶想做的事情(即Task)可以完全不同,但是當細分Task為Activity時,就可能出現Activity功能類似的情況。既然A1、B2已能滿足要求,為何還要重復“發明輪子”呢?另外,通過重用Activity,也可為用戶提供一致的界面和體驗。
了解Android設計理念后,我們來看看Android是如何組織Task及它所包含的Activity的。此處有一個簡單的例子,如圖6-11所示。
:-: 
圖6-11 Task及Back Stack示例
由圖6-11可知:
- 本例中的Task包含4個Activity。用戶可單擊按鈕跳轉到下一個Activity。同時,通過返回鍵可回到上一個Activity。
- 虛線下方是這些Activity的組織方式。Android采用了Stack的方法管理這3個Activity。例如在A1啟動A2后,A2入棧成為棧頂成員,A1成為棧底成員,而界面顯示的是棧頂成員的內容。當按返回鍵時,A3出棧,這時候A2成為棧頂,界面顯示也相應變成了A2。
以上是一個Task的情況。那么,多個Task又會是何種情況呢?如圖6-12所示。
:-: 
圖6-12 多個Task的情況
由圖6-12可知:對多Task的情況來說,系統只支持一個處于前臺的Task,即用戶當前看到的Activity所屬的Task,其余的Task均處于后臺,這些后臺Task內部的Activity保持順序不變。用戶可以一次將整個Task挪到后臺或者置為前臺。
* * * * *
**提示**:用過Android手機的讀者應該知道,長按Home鍵,系統會彈出近期Task列表,使用戶能快速在多個Task間切換。
* * * * *
以上內容從抽象角度介紹了什么是Task,以及Android如何分解Task和管理Activity,那么在實際代碼中,是如何考慮并設計的呢?
(2) 關于ActivityStack的介紹
通過上述分析,我們對Android的設計有了一定了解,那么如何用代碼來實現這一設計呢?此處有兩點需要考慮:
- Task內部Activity的組織方式。由圖6-11可知,Android通過先入后出的方式來組織Activity。數據結構中的Stack即以這種方式工作。
- 多個Task的組織及管理方式。
Android設計了一個ActivityStack類來負責上述工作,它的組成如圖6-13所示。
:-: 
圖6-13 ActivityStack及相關成員
由圖6-13可知:
- Activity由ActivityRecord表示,Task由TaskRecord表示。ActivityRecord的task成員指向該Activity所在的Task。state變量用于表示該Activity所處的狀態(包括INITIALIZING、RESUMED、PAUSED等狀態)。
- ActivityStack用mHistory這個ArrayList保存ActivityRecord。令人大跌眼鏡的是,該mHistory保存了系統中所有Task的ActivityRecord,而不是針對某個Task進行保存。
- ActivityStack的mMainStack成員比較有意思,它代表此ActivityStack是否為主ActivityStack。有主必然有從,但是目前系統中只有一個ActivityStack,并且它的mMainStack為true。從ActivityStack的命名可推測,Android在開發之初也想用ActivityStack來管理單個Task中的ActivityRecord(在ActivityStack.java的注釋中說過,該類為“State and management of asingle stack of activities”),但不知何故,在現在的代碼實現將所有Task的ActivityRecord都放到mHistory中了,并且依然保留mMainStack。
- ActivityStack中沒有成員用于保存TaskRecord。
由上述內容可知,ActivityStack采用數組的方式保存所有Task的ActivityRecord,并且沒有成員保存TaskRecord。這種實現方式有優點亦有缺點:
- 優點是少了TaskRecord一級的管理,直接以ActivityRecord為管理單元。這種做法能降低管理方面的開銷。
- 缺點是弱化了Task的概念,結構不夠清晰。
下面來看ActivityStack中幾個常用的搜索ActivityRecord的函數,代碼如下:
**ActivityStack.java::topRunningActivityLocked**
~~~
/* topRunningActivityLocked:
找到棧中第一個與notTop不同的,并且不處于finishing狀態的ActivityRecord。當notTop為
null時,該函數即返回棧中第一個需要顯示的ActivityRecord。提醒讀者,棧的出入口只能是棧頂。
雖然mHistory是一個數組,但是查找均從數組末端開始,所以其行為也粗略符合Stack的定義
*/
final ActivityRecordtopRunningActivityLocked(ActivityRecord notTop) {
int i =mHistory.size()-1;
while (i>= 0) {
ActivityRecord r = mHistory.get(i);
if (!r.finishing && r != notTop) return r;
i--;
}
returnnull;
}
~~~
類似的函數還有:
**ActivityStack.java::topRunningNonDelayedActivityLocked**
~~~
/* topRunningNonDelayedActivityLocked
與topRunningActivityLocked類似,但ActivityRecord要求增加一項,即delayeResume為
false
*/
final ActivityRecordtopRunningNonDelayedActivityLocked(ActivityRecord notTop) {
int i =mHistory.size()-1;
while(i >= 0) {
ActivityRecord r = mHistory.get(i);
//delayedResume變量控制是否暫緩resume Activity
if (!r.finishing && !r.delayedResume&& r != notTop) return r;
i--;
}
returnnull;
}
~~~
ActivityStack還提供findActivityLocked函數以根據Intent及ActivityInfo來查找匹配的ActivityRecord,同樣,查找也是從mHistory尾端開始,相關代碼如下:
**ActivityStack.java::findActivityLocked**
~~~
private ActivityRecord findActivityLocked(Intentintent, ActivityInfo info) {
ComponentName cls = intent.getComponent();
if(info.targetActivity != null)
cls= new ComponentName(info.packageName, info.targetActivity);
final intN = mHistory.size();
for (inti=(N-1); i>=0; i--) {
ActivityRecord r = mHistory.get(i);
if (!r.finishing)
if (r.intent.getComponent().equals(cls))return r;
}
return null;
}
~~~
另一個findTaskLocked函數的返回值是ActivityRecord,其代碼如下:
**ActivityStack.java::findTaskLocked**
~~~
private ActivityRecord findTaskLocked(Intentintent, ActivityInfo info) {
ComponentName cls = intent.getComponent();
if(info.targetActivity != null)
cls= new ComponentName(info.packageName, info.targetActivity);
TaskRecord cp = null;
final intN = mHistory.size();
for (inti=(N-1); i>=0; i--) {
ActivityRecord r = mHistory.get(i);
//r.task!=cp,表示不搜索屬于同一個Task的ActivityRecord
if(!r.finishing && r.task != cp
&& r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
cp = r.task;
//如果Task的affinity相同,則返回這條ActivityRecord
if(r.task.affinity != null) {
if(r.task.affinity.equals(info.taskAffinity)) return r;
}else if (r.task.intent != null
&&r.task.intent.getComponent().equals(cls)) {
//如果Task Intent的ComponentName相同
return r;
}else if (r.task.affinityIntent != null
&&r.task.affinityIntent.getComponent().equals(cls)) {
//Task affinityIntent考慮
return r;
}//if (r.task.affinity != null)判斷結束
}//if(!r.finishing && r.task != cp......)判斷結束
}//for循環結束
returnnull;
}
~~~
其實,findTaskLocked是根據mHistory中ActivityRecord所屬的Task的情況來進行相應的查找工作。
以上這4個函數均是ActivityStack中常用的函數,如果不需要逐項(case by case)地研究AMS,那么讀者僅需了解這幾個函數的作用即可。
(3) 關于Launch Mode的介紹
Launch Mode用于描述Activity的啟動模式,目前一共有4種模式,分別是standard、singleTop、singleTask和singleInstance。初看它們,較難理解,實際上不過是Android玩的一個“小把戲“而已。啟動模式就是用于控制Activity和Task關系的。
- standard:一個Task中可以有多個相同類型的Activity。注意,此處是相同類型的Activity,而不是同一個Activity對象。例如在Task中有A、B、C、D4個Activity,如果再啟動A類Activity, Task就會變成A、B、C、D、A。最后一個A和第一個A是同一類型,卻并非同一對象。另外,多個Task中也可以有同類型的Activity。
- singleTop:當某Task中有A、B、C、D4個Activity時,如果D想再啟動一個D類型的Activity,那么Task將是什么樣子呢?在singleTop模式下,Task中仍然是A、B、C、D,只不過D的onNewIntent函數將被調用以處理這個新Intent,而在standard模式下,則Task將變成A、B、C、D、D,最后的D為新創建的D類型Activity對象。在singleTop這種模式下,只有目標Acitivity當前正好在棧頂時才有效,例如只有處于棧頂的D啟動時才有用,如果D啟動不處于棧頂的A、B、C等,則無效。
- singleTask:在這種啟動模式下,該Activity只存在一個實例,并且將和一個Task綁定。當需要此Activity時,系統會以onNewIntent方式啟動它,而不會新建Task和Activity。注意,該Activity雖只有一個實例,但是在Task中除了它之外,還可以有其他的Activity。
- singleInstance:它是singleTask的加強版,即一個Task只能有這么一個設置了singleInstance的Activity,不能再有別的Activity。而在singleTask模式中,Task還可以有其他的Activity。
* * * * *
**注意**,Android建議一般的應用開發者不要輕易使用最后兩種啟動模式。因為這些模式雖然名意上為Launch Mode,但是它們也會影響Activity出棧的順序,導致用戶按返回鍵返回時導致不一致的用戶體驗。
* * * * *
除了啟動模式外,Android還有其他一些標志用于控制Activity及Task之間的關系。這里只列舉一二,詳細信息請參閱SDK文檔中Intent的相關說明。
- FLAG_ACTIVITY_NEW_TASK:將目標Activity放到一個新的Task中。
- FLAG_ACTIVITY_CLEAR_TASK:當啟動一個Activity時,先把和目標Activity有關聯的Task“干掉“,然后啟動一個新的Task,并把目標Activity放到新的Task中。該標志必須和FLAG_ACTIVITY_NEW_TASK標志一起使用。
- FLAG_ACTIVITY_CLEAR_TOP:當啟動一個不處于棧頂的Activity時候,先把排在它前面的Activity“干掉”。例如Task有A、B、C、D4個Activity,要要啟動B,直接把C、D“干掉”,而不是新建一個B。
* * * * *
**提示**:這些啟動模式和標志,在筆者看來很像洗撲克牌時的手法,因此可以稱之為小把戲。雖是小把戲,但是相關代碼的邏輯及分支卻異常繁雜,我們應從更高的角度來看待它們。
* * * * *
介紹完上面的知識后,下面來分析ActivityStack的startActivityMayWait函數。
2. ActivityStack的startActivityMayWait函數分析
startActivityMayWait函數的目標是啟動com.dfp.test.TestActivity,假設系統之前沒有啟動過該Activity,本例最終的結果將是:
- 由于在am中設置了FLAG_ACTIVITY_NEW_TASK標志,因此除了會創建一個新的ActivityRecord外,還會新創建一個TaskRecord。
- 還需要啟動一個新的應用進程以加載并運行com.dfp.test.TestActivity的一個實例。
- 如果TestActivity不是Home,還需要停止當前正在顯示的Activity。
好了,將這個函數分三部分進行介紹,先來分析第一部分。
(1) startActivityMayWait分析之一
**ActivityStack.java::startActivityMayWait**
~~~
final int startActivityMayWait(IApplicationThreadcaller, int callingUid,
Intentintent, String resolvedType, Uri[] grantedUriPermissions,
intgrantedMode, IBinder resultTo,
StringresultWho, int requestCode, boolean onlyIfNeeded,
booleandebug, String profileFile, ParcelFileDescriptor profileFd,
booleanautoStopProfiler, WaitResult outResult, Configuration config) {
......
//在本例中,已經指明了Component,這樣可省去為Intent匹配搜索之苦
booleancomponentSpecified = intent.getComponent() != null;
//創建一個新的Intent,防止客戶傳入的Intent被修改
intent =new Intent(intent);
//查詢滿足條件的ActivityInfo,在resolveActivity內部和PKMS交互,讀者不妨自己
//嘗試分析該函數
ActivityInfoaInfo = resolveActivity(intent, resolvedType, debug,
profileFile, profileFd,autoStopProfiler);
synchronized(mService) {
int callingPid;
if (callingUid >= 0) {
callingPid= -1;
} else if (caller == null) {//本例中,caller為null
callingPid= Binder.getCallingPid();//取出調用進程的Pid
//取出調用進程的Uid。在本例中,調用進程是am,它由shell啟動
callingUid= Binder.getCallingUid();
} else {
callingPid= callingUid = -1;
}// if (callingUid >= 0)判斷結束
//在本例中config為null
mConfigWillChange= config != null
&& mService.mConfiguration.diff(config) != 0;
finallong origId = Binder.clearCallingIdentity();
if (mMainStack && aInfo != null&& (aInfo.applicationInfo.flags&
ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0){
/*
AndroidManifest.xml中的Application標簽可以聲明一個cantSaveState
屬性,設置了該屬性的Application將不享受系統提供的狀態保存/恢復功能。
當一個Application退到后臺時,系統會為它保存狀態,當調度其到前臺運行時, 將恢復它之前的狀態,以保證用戶體驗的連續性。聲明了該屬性的Application被稱為
“heavy weight process”。可惜系統目前不支持該屬性,因為PackageParser
將不解析該屬性。詳情請見PackageParser.java parseApplication函數
*/
}
......//待續
~~~
startActivityMayWait第一階段的工作內容相對較簡單:
- 首先需要通過PKMS查找匹配該Intent的ActivityInfo。
- 處理FLAG_CANT_SAVE_STATE的情況,但系統目前不支持此情況。
- 另外,獲取調用者的pid和uid。由于本例的caller為null,故所得到的pid和uid均為am所在進程的uid和pid。
下面介紹startActivityMayWait第二階段的工作。
(2) startActivityMayWait分析之二
**ActivityStack.java::startActivityMayWait**
~~~
//調用此函數啟動Activity,將返回值保存到res
int res = startActivityLocked(caller, intent,resolvedType,
grantedUriPermissions, grantedMode, aInfo,
resultTo, resultWho, requestCode, callingPid, callingUid,
onlyIfNeeded, componentSpecified, null);
//如果configuration發生變化,則調用AMS的updateConfigurationLocked
//進行處理。關于這部分內容,讀者學完本章后可自行分析
if(mConfigWillChange && mMainStack) {
mService.enforceCallingPermission(
android.Manifest.permission.CHANGE_CONFIGURATION,
"updateConfiguration()");
mConfigWillChange= false;
mService.updateConfigurationLocked(config,null, false);
}
~~~
此處,啟動Activity的核心函數是startActivityLocked,該函數異常復雜,將用一節專門分析。下面先繼續分析startActivityMayWait第三階段的工作。
(3) startActivityMayWait分析之三
**ActivityStack.java::startActivityMayWait**
~~~
if(outResult != null) {
outResult.result = res;//設置啟動結果
if(res == IActivityManager.START_SUCCESS) {
//將該結果加到mWaitingActivityLaunched中保存
mWaitingActivityLaunched.add(outResult);
do {
try {
mService.wait();//等待啟動結果
}
} while (!outResult.timeout && outResult.who == null);
}else if (res == IActivityManager.START_TASK_TO_FRONT) {
......//處理START_TASK_TO_FRONT結果,讀者可自行分析
}
}//if(outResult!= null)結束
return res;
}
}
~~~
第三階段的工作就是根據返回值做一些處理,那么res返回成功(即res== IActivityManager.START_SUCCESS的時候)后為何還需要等待呢?
這是因為目標Activity要運行在一個新的應用進程中,就必須等待那個應用進程正常啟動并處理相關請求。注意,只有am設置了-W選項,才會進入wait這一狀態。
[^①]:http://www.merriam-webster.com/dictionary/activity中第六條解釋。
- 前言
- 第1章 搭建Android源碼工作環境
- 1.1 Android系統架構
- 1.2 搭建開發環境
- 1.2.1 下載源碼
- 1.2.2 編譯源碼
- 1.2.3 利用Eclipse調試system_process
- 1.3 本章小結
- 第2章 深入理解Java Binder和MessageQueue
- 2.1 概述
- 2.2 Java層中的Binder架構分析
- 2.2.1 Binder架構總覽
- 2.2.2 初始化Java層Binder框架
- 2.2.3 addService實例分析
- 2.2.4 Java層Binder架構總結
- 2.3 心系兩界的MessageQueue
- 2.3.1 MessageQueue的創建
- 2.3.2 提取消息
- 2.3.3 nativePollOnce函數分析
- 2.3.4 MessageQueue總結
- 2.4 本章小結
- 第3章 深入理解SystemServer
- 3.1 概述
- 3.2 SystemServer分析
- 3.2.1 main函數分析
- 3.2.2 Service群英會
- 3.3 EntropyService分析
- 3.4 DropBoxManagerService分析
- 3.4.1 DBMS構造函數分析
- 3.4.2 dropbox日志文件的添加
- 3.4.3 DBMS和settings數據庫
- 3.5 DiskStatsService和DeviceStorageMonitorService分析
- 3.5.1 DiskStatsService分析
- 3.5.2 DeviceStorageManagerService分析
- 3.6 SamplingProfilerService分析
- 3.6.1 SamplingProfilerService構造函數分析
- 3.6.2 SamplingProfilerIntegration分析
- 3.7 ClipboardService分析
- 3.7.1 復制數據到剪貼板
- 3.7.2 從剪切板粘貼數據
- 3.7.3 CBS中的權限管理
- 3.8 本章小結
- 第4章 深入理解PackageManagerService
- 4.1 概述
- 4.2 初識PackageManagerService
- 4.3 PKMS的main函數分析
- 4.3.1 構造函數分析之前期準備工作
- 4.3.2 構造函數分析之掃描Package
- 4.3.3 構造函數分析之掃尾工作
- 4.3.4 PKMS構造函數總結
- 4.4 APK Installation分析
- 4.4.1 adb install分析
- 4.4.2 pm分析
- 4.4.3 installPackageWithVerification函數分析
- 4.4.4 APK 安裝流程總結
- 4.4.5 Verification介紹
- 4.5 queryIntentActivities分析
- 4.5.1 Intent及IntentFilter介紹
- 4.5.2 Activity信息的管理
- 4.5.3 Intent 匹配查詢分析
- 4.5.4 queryIntentActivities總結
- 4.6 installd及UserManager介紹
- 4.6.1 installd介紹
- 4.6.2 UserManager介紹
- 4.7 本章學習指導
- 4.8 本章小結
- 第5章 深入理解PowerManagerService
- 5.1 概述
- 5.2 初識PowerManagerService
- 5.2.1 PMS構造函數分析
- 5.2.2 init分析
- 5.2.3 systemReady分析
- 5.2.4 BootComplete處理
- 5.2.5 初識PowerManagerService總結
- 5.3 PMS WakeLock分析
- 5.3.1 WakeLock客戶端分析
- 5.3.2 PMS acquireWakeLock分析
- 5.3.3 Power類及LightService類介紹
- 5.3.4 WakeLock總結
- 5.4 userActivity及Power按鍵處理分析
- 5.4.1 userActivity分析
- 5.4.2 Power按鍵處理分析
- 5.5 BatteryService及BatteryStatsService分析
- 5.5.1 BatteryService分析
- 5.5.2 BatteryStatsService分析
- 5.5.3 BatteryService及BatteryStatsService總結
- 5.6 本章學習指導
- 5.7 本章小結
- 第6章 深入理解ActivityManagerService
- 6.1 概述
- 6.2 初識ActivityManagerService
- 6.2.1 ActivityManagerService的main函數分析
- 6.2.2 AMS的 setSystemProcess分析
- 6.2.3 AMS的 installSystemProviders函數分析
- 6.2.4 AMS的 systemReady分析
- 6.2.5 初識ActivityManagerService總結
- 6.3 startActivity分析
- 6.3.1 從am說起
- 6.3.2 AMS的startActivityAndWait函數分析
- 6.3.3 startActivityLocked分析
- 6.4 Broadcast和BroadcastReceiver分析
- 6.4.1 registerReceiver流程分析
- 6.4.2 sendBroadcast流程分析
- 6.4.3 BROADCAST_INTENT_MSG消息處理函數
- 6.4.4 應用進程處理廣播分析
- 6.4.5 廣播處理總結
- 6.5 startService之按圖索驥
- 6.5.1 Service知識介紹
- 6.5.2 startService流程圖
- 6.6 AMS中的進程管理
- 6.6.1 Linux進程管理介紹
- 6.6.2 關于Android中的進程管理的介紹
- 6.6.3 AMS進程管理函數分析
- 6.6.4 AMS進程管理總結
- 6.7 App的 Crash處理
- 6.7.1 應用進程的Crash處理
- 6.7.2 AMS的handleApplicationCrash分析
- 6.7.3 AppDeathRecipient binderDied分析
- 6.7.4 App的Crash處理總結
- 6.8 本章學習指導
- 6.9 本章小結
- 第7章 深入理解ContentProvider
- 7.1 概述
- 7.2 MediaProvider的啟動及創建
- 7.2.1 Context的getContentResolver函數分析
- 7.2.2 MediaStore.Image.Media的query函數分析
- 7.2.3 MediaProvider的啟動及創建總結
- 7.3 SQLite創建數據庫分析
- 7.3.1 SQLite及SQLiteDatabase家族
- 7.3.2 MediaProvider創建數據庫分析
- 7.3.3 SQLiteDatabase創建數據庫的分析總結
- 7.4 Cursor 的query函數的實現分析
- 7.4.1 提取query關鍵點
- 7.4.2 MediaProvider 的query分析
- 7.4.3 query關鍵點分析
- 7.4.4 Cursor query實現分析總結
- 7.5 Cursor close函數實現分析
- 7.5.1 客戶端close的分析
- 7.5.2 服務端close的分析
- 7.5.3 finalize函數分析
- 7.5.4 Cursor close函數總結
- 7.6 ContentResolver openAssetFileDescriptor函數分析
- 7.6.1 openAssetFileDescriptor之客戶端調用分析
- 7.6.2 ContentProvider的 openTypedAssetFile函數分析
- 7.6.3 跨進程傳遞文件描述符的探討
- 7.6.4 openAssetFileDescriptor函數分析總結
- 7.7 本章學習指導
- 7.8 本章小結
- 第8章 深入理解ContentService和AccountManagerService
- 8.1 概述
- 8.2 數據更新通知機制分析
- 8.2.1 初識ContentService
- 8.2.2 ContentResovler 的registerContentObserver分析
- 8.2.3 ContentResolver的 notifyChange分析
- 8.2.4 數據更新通知機制總結和深入探討
- 8.3 AccountManagerService分析
- 8.3.1 初識AccountManagerService
- 8.3.2 AccountManager addAccount分析
- 8.3.3 AccountManagerService的分析總結
- 8.4 數據同步管理SyncManager分析
- 8.4.1 初識SyncManager
- 8.4.2 ContentResolver 的requestSync分析
- 8.4.3 數據同步管理SyncManager分析總結
- 8.5 本章學習指導
- 8.6 本章小結