ContentProvider按照一定规则暴露自己的接口给其它应用来访问自己应用的数据(其实就是自定义增删改查接口并暴露出去,让别的应用访问自己的数据)。当其他应用需要用到该应用的数据时,可以使用ContentResolver,而通过ContentResolver我们可以完成两大功能:
1 通过其对ContentProvider中的数据进行添加、删除、修改和查询操作
2 通过其来监听ContentProvider中数据的变化
那ContentResolver是如何实现这些功能的呢?其实,它内部主要就是调用了ContentService的相应方法,这就说明数据的更新等操作主要由ContentService来完成的。
接下来,我们就结合ContentResolver的使用来分析ContentService
在SystemServer的startOtherServices方法中,有这么一段代码
contentService = ContentService.main(context,mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL);
......
......
// 省略部分代码
try {
if (contentService != null)
contentService.systemReady();
} catch (Throwable e) {
reportWtf("making Content Service ready", e);
}
在这里调用ContentService的main方法创建了一个ContentService实例,并调用了它的systemReady()方法。我们分开两步分析:
1. ContentService.main()分析
public static ContentService main(Context context, boolean factoryTest) {
ContentService service = new ContentService(context, factoryTest);
ServiceManager.addService(ContentResolver.CONTENT_SERVICE_NAME, service);
return service;
}
这里主要就是创建了一个ContentService,并将其添加到ServiceManager中。我们进去看下它的构造函数
/*package*/ ContentService(Context context, boolean factoryTest) {
mContext = context;
mFactoryTest = factoryTest;
}
这里只是简单的保存了两个变量的引用在本地
2. contentService.systemReady()
public void systemReady() {
getSyncManager();
}
private SyncManager getSyncManager() {
if (SystemProperties.getBoolean("config.disable_network", false)) {
return null;
}
synchronized(mSyncManagerLock) {
try {
// Try to create the SyncManager, return null if it fails (e.g. the disk is full).
if (mSyncManager == null) mSyncManager = new SyncManager(mContext, mFactoryTest);
} catch (SQLiteException e) {
Log.e(TAG, "Can't create SyncManager", e);
}
return mSyncManager;
}
}
假如网络被禁止,则不获取SyncManager服务。SyncManager是数据同步的主要类
我们从ContentResolver入手:
/** * Register an observer class that gets callbacks when data identified by a * given content URI changes. * * @param uri The URI to watch for changes. This can be a specific row URI, or a base URI * for a whole class of content. * @param notifyForDescendents If <code>true</code> changes to URIs beginning with <code>uri</code> * will also cause notifications to be sent. If <code>false</code> only changes to the exact URI * specified by <em>uri</em> will cause notifications to be sent. If <code>true</code>, any URI values * at or below the specified URI will also trigger a match. * @param observer The object that receives callbacks when changes occur. * @see #unregisterContentObserver */
public final void registerContentObserver(Uri uri, boolean notifyForDescendents,
ContentObserver observer)
{
registerContentObserver(uri, notifyForDescendents, observer, UserHandle.myUserId());
}
/** @hide - designated user version */
public final void registerContentObserver(Uri uri, boolean notifyForDescendents,
ContentObserver observer, int userHandle)
{
try {
getContentService().registerContentObserver(uri, notifyForDescendents,
observer.getContentObserver(), userHandle);
} catch (RemoteException e) {
}
}
从上边的函数可以看到,ContentResolver的registerContentObserver()方法内部其实是调用了ContentService的registerContentObserver方法,我们进入查看
public void registerContentObserver(Uri uri, boolean notifyForDescendants,
IContentObserver observer) {
registerContentObserver(uri, notifyForDescendants, observer,
UserHandle.getCallingUserId());
}
/** * Register a content observer tied to a specific user's view of the provider. * @param userHandle the user whose view of the provider is to be observed. May be * the calling user without requiring any permission, otherwise the caller needs to * hold the INTERACT_ACROSS_USERS_FULL permission. Pseudousers USER_ALL and * USER_CURRENT are properly handled; all other pseudousers are forbidden. */
@Override
public void registerContentObserver(Uri uri, boolean notifyForDescendants,
IContentObserver observer, int userHandle) {
if (observer == null || uri == null) {
throw new IllegalArgumentException("You must pass a valid uri and observer");
}
enforceCrossUserPermission(userHandle,
"no permission to observe other users' provider view");
if (userHandle < 0) {
if (userHandle == UserHandle.USER_CURRENT) {
userHandle = ActivityManager.getCurrentUser();
} else if (userHandle != UserHandle.USER_ALL) {
throw new InvalidParameterException("Bad user handle for registerContentObserver: "
+ userHandle);
}
}
synchronized (mRootNode) {
mRootNode.addObserverLocked(uri, observer, notifyForDescendants, mRootNode,
Binder.getCallingUid(), Binder.getCallingPid(), userHandle);
if (false) Log.v(TAG, "Registered observer " + observer + " at " + uri +
" with notifyForDescendants " + notifyForDescendants);
}
}
ContentService的registerContentObserver方法内部实现很简单:就是将uri和observer的对应关系保存到mRootNode变量中
我们从ContentResolver入手:
public void notifyChange(Uri uri, ContentObserver observer) {
notifyChange(uri, observer, true /* sync to network */);
}
public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
notifyChange(uri, observer, syncToNetwork, UserHandle.myUserId());
}
public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork,
int userHandle) {
try {
getContentService().notifyChange(
uri, observer == null ? null : observer.getContentObserver(),
observer != null && observer.deliverSelfNotifications(), syncToNetwork,
userHandle);
} catch (RemoteException e) {
}
}
从上边的函数可以看到,ContentResolver的notifyChange()方法内部其实是调用了ContentService的notifyChange方法,我们进入查看
try {
ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
synchronized (mRootNode) {
mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications,
userHandle, calls);
}
final int numCalls = calls.size();
for (int i=0; i<numCalls; i++) {
ObserverCall oc = calls.get(i);
try {
oc.mObserver.onChange(oc.mSelfChange, uri, userHandle);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Notified " + oc.mObserver + " of " + "update at " + uri);
}
} catch (RemoteException ex) {
synchronized (mRootNode) {
Log.w(TAG, "Found dead observer, removing");
IBinder binder = oc.mObserver.asBinder();
final ArrayList<ObserverNode.ObserverEntry> list
= oc.mNode.mObservers;
int numList = list.size();
for (int j=0; j<numList; j++) {
ObserverNode.ObserverEntry oe = list.get(j);
if (oe.observer.asBinder() == binder) {
list.remove(j);
j--;
numList--;
}
}
}
}
}
if (syncToNetwork) {
SyncManager syncManager = getSyncManager();
if (syncManager != null) {
syncManager.scheduleLocalSync(null /* all accounts */, callingUserHandle, uid,
uri.getAuthority());
}
} finally {
restoreCallingIdentity(identityToken);
}
上边主要有两大操作:
- 从mRootNode中获取所有匹配的ContentObserver并保存在变量calls中,遍历calls,调用每个ContentObserver的onChange()方法。假如出现异常:”Found dead observer, removing”
- 假如syncToNetwork为true,则调用syncManager.scheduleLocalSync()进行同步