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);
...
}