ContentProvider的實現及數據庫共享原理,強烈推介老羅的四篇情景分析文章:
Android應用程序組件Content Provider簡要介紹和學習計劃
Android應用程序組件Content Provider應用實例
Android應用程序組件Content Provider的啓動過程源代碼分析
Android應用程序組件Content Provider在應用程序之間共享數據的原理分析
數據庫的代碼分佈;
1、frameworks/base/core/java/android/provider/
.
├── AlarmClock.java
├── Applications.java
├── BaseColumns.java
├── BrowserContract.java
├── Browser.java
├── CalendarContract.java
├── CallLog.java
├── ContactsContract.java
├── Contacts.java
├── Downloads.java
├── DrmStore.java
├── LiveFolders.java
├── MediaStore.java
├── OpenableColumns.java
├── package.html
├── SearchRecentSuggestions.java
├── Settings.java
├── SocialContract.java
├── SyncConstValue.java
├── SyncStateContract.java
├── Telephony.java
├── UserDictionary.java
└── VoicemailContract.java
定義相關的表,字段,CONTENT_URI等其他公共數據成員。
2、packages/providers
.
├── ApplicationsProvider
├── CalendarProvider
├── ContactsProvider
├── DownloadProvider
├── DrmProvider
├── GoogleContactsProvider
├── MediaProvider
├── TelephonyProvider
└── UserDictionaryProvider
數據庫的實現,包括數據庫的創建,增刪改查等外部接口。
此目錄下所有的代碼,packages/app下都有對應的apk,但是之所以將provider的代碼獨立成一個額外的apk,我認爲的好處有如下幾點:
- 避免代碼(數據庫文件)過於龐大
- 這樣的實現有點類似於MVC模型,數據的使用與實現分開,可以最大限度的保持第三方應用的友好性,例如再設計一個聯繫人的apk,可以不用再實現一個數據庫。
3、apk內部實現的數據庫
上述第2條中的分離方式,並不適合所有的數據庫文件,
例如:packages/apps/Browser/src/com/android/browser/provider/
.
├── BrowserProvider2.java
├── BrowserProvider.java
├── SnapshotProvider.java
└── SQLiteContentProvider.java
4、除了通過ContentProvider封裝來實現應用程序之間數據庫共享,還可以通過Manager-Service的形式來實現
例如:frameworks/base/core/java/android/accounts/
.
├── AccountManager.java
├── AccountManagerService.java
├── IAccountManager.aidl
...
└── OperationCanceledException.java
AccountManagerService.java中實現數據庫了操作,但是對外部是透明的,也就是說應用層並不知道它對account的存儲是通過數據庫實現,只是提供 IAccountManager.aidl作爲更加具體的接口,隱匿了query, insert等操作。
interface IAccountManager {
String getPassword(in Account account);
String getUserData(in Account account, String key);
AuthenticatorDescription[] getAuthenticatorTypes();
Account[] getAccounts(String accountType);
Account[] getAccountsAsUser(String accountType, int userId);
...
}