ContactsProvider2
本篇不全也不細,只是根據按照個人理解和工作中遇到的問題,總結了個人認為的要點。
1. Android的數據庫體系
- 1.1. 概述
- 1.2 uri結構
2. ContactsProvider2
- 2.1. 概述
- 2.2. Contacts2.db中的表
- 2.3. ContactProvider2中的實現
- 2.4. 批量訪問
1. Android的數據庫體系
1.1. 概述
Android的數據庫體系可以分為三個層次:
ContentProvider不支持線程安全,但SQLite是支持線程安全的(編譯前將 宏SQLITE_THREADSAFE 設置為1)。
多個進程可以同時打開一個database,而且可以同時執行SELECT操作,但是同一時間只能有一個進行修改操作。
下面的簡圖展示了我們使用uri訪問database的方式,其中ContentProvider在ActivityManagerService中的register可能是自己所在進程啟動時做的,也可能是ActivityManagerService收到uri請求后啟動ContentProvider時做的。ContentResolver和ActivityManagerService根據uri中的"authority"來確定要訪問的ContentProvider。
1.2 uri結構
基本結構
[scheme:]scheme-specific-part[#fragment]
進一步劃分
[scheme:][//authority][path][?query][#fragment]
path可以有多個,每個用/連接,比如scheme://authority/path1/path2/path3?query#fragment。
query參數可以帶有對應的值,也可以不帶,如果帶對應的值用=表示,如:
scheme://authority/path1/path2/path3?id = 1#fragment,這里有一個參數id,它的值是1
query參數可以有多個,每個用&連接,如
scheme://authority/path1/path2/path3?id = 1&name = xiaofang&age#fragment
這里有三個參數:
參數1:id,其值是:1
參數2:name,其值是:xiaofang
參數3:age,沒有對它賦值
在android中,scheme、authority都是必須要有的,而至于path、query和fragment,它們都是選擇性的,可以有也可以沒有,但順序不能變,比如:
"path"可不要:scheme://authority?query#fragment
"path"和"query"可都不要:scheme://authority#fragment
"query"和"fragment"可都不要:scheme://authority/path
“path”,“query”,"fragment"都不要:scheme://authority
等等……
終極劃分
[scheme:][//host:port][path][?query][#fragment]
2. ContactsProvider2
2.1. 概述
ContactsProvider2是Android一個很成熟的源生組件,用于管理聯系人數據相關的存儲區。Google對ContactsProvider2有一個比較詳細的介紹,下面是相關鏈接:
https://developer.android.com/guide/topics/providers/contacts-provider
ContactsProvider2管理了兩個database,一個是"contacts2.db",另外一個是"profile.db";本篇著重寫contacts.db相關的內容。
2.2. Contacts2.db中的表
“contacts2.db”數據庫中存儲了聯系人、通話記錄和Account等數據。
由于聯系人的信息字段比較多,包含了號碼、地址、Email和頭像等信息,所以數據庫中的數據表也比較多;為了提高查詢速度,還創建了視圖和索引;另外還有觸發器。
Android P源碼中數據表有30多個,視圖有11個;這里就不一一列出了,太占地方了,哈哈。
我們需要搞清楚這些表之間的關系,特別是幾個存儲重要信息的表,下面是幾個重要表的ER圖
表“Contacts”中的數據是在數據插入表“raw_contact”之后,在Transaction的回調onCommit調用序列中插入的。
聯系人相關的數據并沒有存儲在raw_contact表中,而是存儲在了Data表中;一條raw_contact數據在Data表中對應多條數據。Data表中有15個data字段,每個字段存儲的是什么信息要根據列"mimetype_id"來決定,該列的取值來自"account"表的主鍵"_ID"。
協定類ContactsContract.java中為data字段定義了映射名稱類,如下表:
| ContactsContract.CommonDataKinds.StructuredName | 與該數據行關聯的raw contact的姓名數據。 | 一位raw contact只有其中一行。 |
| ContactsContract.CommonDataKinds.Photo | 與該數據行關聯的raw contact的主要照片。 | 一位raw contact只有其中一行。 |
| ContactsContract.CommonDataKinds.Email | 與該數據行關聯的raw contact的電子郵件地址。 | 一位raw contact可有多個電子郵件地址。 |
| ContactsContract.CommonDataKinds.StructuredPostal | 與該數據行關聯的raw contact的郵政地址。 | 一位raw contact可有多個郵政地址。 |
| ContactsContract.CommonDataKinds.GroupMembership | 將raw contact鏈接到聯系人提供程序內某個組的標識符。 | 組是帳戶類型和帳戶名稱的一項可選功能。聯系人組部分對其進行了更詳細的描述。 |
以“ContactsContract.CommonDataKinds.Email”和“ContactsContract.CommonDataKinds.StructuredName”為例,前者用于聯系人的Email信息,后者用于聯系人的名字信息; 它們分別在Data表中有一條記錄,而且都使用了“data1”、“data2”和“data3”這三個字段,但是每個字段在兩條記錄中分別存儲了不同的信息,如下圖:
2.3. ContactProvider2中的實現
下面是ContactsProvider2的類繼承關系圖:
ContactsProvider2直接繼承了AbstractContactsProvider.java這個類,它的很多功能都繼承自這個抽象父類,看代碼時這個抽象父類的代碼也是重點。
ContactsProvider2中定義了UriMatcher對象sUriMatcher,并在static塊中進行了初始化:
ContractsProvider2會將接收到的uri和sUriMatcher進行匹配,即根據uri中的path確定要訪問的table。
比如,我們向Data表中增加一條數據記錄,那么我們會使用
insertInTransaction方法使用sUriMatcher進行匹配后返回”DATA”,然后在switch的對應case語句中處理這條增加數據的請求。
由于"contacts2.db"中的表比較多,而App層只是通過uri發送請求,那么相關表直接的數據維護邏輯是在ContactsProvider2中完成的,這也方便了App層的使用。為了維護數據一致性和原子性等,ContactsProvider2.java的增/刪/改都使用了事務(Transaction),下面的流程圖展示了insert操作的事務處理流程,其他操作類似:
2.4. 批量訪問
可以使用 ContentProviderOperation 類中的方法創建一批訪問調用,然后通過 ContentResolver.applyBatch(…) 應用這些調用。如果某次批量修改需執行大量操作,則可能會阻塞其他進程,導致整體用戶體驗不佳??梢詫⑾雸绦械男薷牟僮鞅M量分散到各個集合中,并為一項或多項操作設置掛起點。掛起點是一個 ContentProviderOperation 對象,并且其 isYieldAllowed() 值設置為 true。當ContactsProvider2遇到掛起點時,它會暫停其工作,讓其他進程運行,并關閉當前事務。當ContactsProvider2再次啟動時,它會繼續執行 ArrayList 中的下一項操作,并啟動新事務。
掛起點會導致每次調用 applyBatch() 時產生多個事務。因此,應為一組相關數據行的最后一項操作設置掛起點。例如,應該為一組操作中添加raw contact行及其關聯數據行的最后一項操作設置掛起點,或者針對一組與某位聯系人相關的行的最后一項操作設置掛起點。
掛起點也是一個原子操作單元。無論訪問成功還是失敗,兩個掛起點之間的所有訪問均以一個單元的形式呈現。如果不設置任何掛起點,則最小的原子操作即為整個批量操作。如果使用掛起點,則可以防止操作降低系統性能,還可確保部分操作為原子操作。
結束
總結
以上是生活随笔為你收集整理的ContactsProvider2的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: protues 选项卡说明
- 下一篇: instantclient oracle