ContentProvider分析
ContentProvider何時創建呢?這是一個值得深思的問題?據我這兩天的了解是在你要用到的時候才會調用ContentProvider的onCreate函數進行創建。你就會什么時候叫要用到的時候呢?比如你要查詢或刪除修改數據庫的時候通過ContentResolver的quire或delete來操縱數據時就會調用ContentProvider的onCreate函數,若已經創建了數據庫就不會再次創建。可以通過ContentResolver的源碼來理解
- public final Cursor query(Uri uri, String[] projection,
- String selection, String[] selectionArgs, String sortOrder) {
- IContentProvider provider = acquireProvider(uri);
- if (provider == null) {
- return null;
- }
- try {
- Cursor qCursor = provider.query(uri, projection, selection, selectionArgs, sortOrder);
- if(qCursor == null) {
- releaseProvider(provider);
- return null;
- }
- //Wrap the cursor object into CursorWrapperInner object
- return new CursorWrapperInner(qCursor, provider);
- } catch (RemoteException e) {
- releaseProvider(provider);
- return null;
- } catch(RuntimeException e) {
- releaseProvider(provider);
- throw e;
- }
- }
ContentResolver中的acquireProvider(uri)來獲得對應的Provider.通過uri中的Authority的字段知道是要用哪個provider.也就是為什么要在Provider的menifester.xml中<provider.. android:authority="">.
下面對android的幾個已有的Provider的進行說明一下:
1,SettingsProvider
- <!-- Permission to write Gservices in SettingsProvider -->
- <permission android:name="android.permission.WRITE_GSERVICES"
- android:label="@string/permlab_writeGservices"
- android:description="@string/permdesc_writeGservices"
- android:protectionLevel="signature" />
- <application android:allowClearUserData="false"
- android:label="Settings Storage"
- android:icon="@drawable/ic_launcher_settings">
- <provider android:name="SettingsProvider" android:authorities="settings"
- android:process="system" android:multiprocess="false"
- android:writePermission="android.permission.WRITE_SETTINGS"
- android:initOrder="100" />
- </application>
- /manifest>
若你仔細查看SettingsProvider就會發現在它的manifester.xml中在android:process="system" 和android:sharedUserId="android.uid.system
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.providers.settings"
android:sharedUserId="android.uid.system">,我猜測它就是多了這兩條語句使得系統加載完就加載它。若你注意開機的logcat就會發現04-29 02:32:20.612: INFO/ActivityThread(79): Publishing provider settings: com.android.providers.settings.SettingsProvider通過ActivityThread開始往上追你就會發現
從SystemServer.java中的
- Log.i(TAG, "Starting System Content Providers.");
- ActivityManagerService.installSystemProviders();
- public static final void installSystemProviders() {
- [color=blue]ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID);[/color]
- List providers = mSelf.generateApplicationProvidersLocked(app);
- mSystemThread.installSystemProviders(providers);
- }
再到ActivityThread.java:
- public final void installSystemProviders(List providers) {
- if (providers != null) {
- installContentProviders(mInitialApplication,
- (List<ProviderInfo>)providers);
- }
- }
- private final void installContentProviders(
- Context context, List<ProviderInfo> providers) {
- final ArrayList<IActivityManager.ContentProviderHolder> results =
- new ArrayList<IActivityManager.ContentProviderHolder>();
- Iterator<ProviderInfo> i = providers.iterator();
- while (i.hasNext()) {
- ProviderInfo cpi = i.next();
- StringBuilder buf = new StringBuilder(128);
- buf.append("Publishing provider ");
- buf.append(cpi.authority);
- buf.append(": ");
- buf.append(cpi.name);
- Log.i(TAG, buf.toString());
- IContentProvider cp = installProvider(context, null, cpi, false);
- if (cp != null) {
- IActivityManager.ContentProviderHolder cph =
- new IActivityManager.ContentProviderHolder(cpi);
- cph.provider = cp;
- results.add(cph);
- // Don't ever unload this provider from the process.
- synchronized(mProviderMap) {
- mProviderRefCountMap.put(cp.asBinder(), new ProviderRefCount(10000));
- }
- }
- }
2,CalendarProvider
Manifester.xml
- <receiver android:name="CalendarReceiver">
- <intent-filter>
- <action android:name="android.intent.action.BOOT_COMPLETED" />
- </intent-filter>
- </receiver> <provider android:name="CalendarProvider" android:authorities="calendar"
- android:syncable="true" android:multiprocess="false"
- android:readPermission="android.permission.READ_CALENDAR"
- android:writePermission="android.permission.WRITE_CALENDAR" />
并不采用了SettingsProvider的方式而是通過了android.intent.action.BOOT_COMPLETED的方式:
CalendarReceiver.java
- public class CalendarReceiver extends BroadcastReceiver {
- static final String SCHEDULE = "com.android.providers.calendar.SCHEDULE_ALARM";
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- ContentResolver cr = context.getContentResolver();
- CalendarProvider provider;
- IContentProvider icp = cr.acquireProvider("calendar");
- provider = (CalendarProvider) ContentProvider.
- coerceToLocalContentProvider(icp);
- if (action.equals(SCHEDULE)) {
- provider.scheduleNextAlarm(false /* do not remove alarms */);
- } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
- provider.bootCompleted();
- }
- cr.releaseProvider(icp);
- }
- }
posted on 2011-02-18 14:51 九寶 閱讀(1869) 評論(0) 編輯 收藏 所屬分類: android