本文共 7742 字,大约阅读时间需要 25 分钟。
在前面这篇文章 介绍的应用程序Acticle中,当调用ArticlesAdapter类的insertArticle往ArticlesProvider中增加一个文章信息条目时: -
public class ArticlesAdapter { -
-
-
public long insertArticle(Article article) { -
ContentValues values = new ContentValues(); -
values.put(Articles.TITLE, article.getTitle()); -
values.put(Articles.ABSTRACT, article.getAbstract()); -
values.put(Articles.URL, article.getUrl()); -
-
Uri uri = resolver.insert(Articles.CONTENT_URI, values); -
String itemId = uri.getPathSegments().get(1); -
-
return Integer.valueOf(itemId).longValue(); -
-
-
-
便会进入到应用程序ArticlesProvider中的ArticlesProvider类的insert函数中: -
public class ArticlesProvider extends ContentProvider { -
-
-
-
public Uri insert(Uri uri, ContentValues values) { -
if(uriMatcher.match(uri) != Articles.ITEM) { -
throw new IllegalArgumentException("Error Uri: " + uri); -
-
-
SQLiteDatabase db = dbHelper.getWritableDatabase(); -
-
long id = db.insert(DB_TABLE, Articles.ID, values); -
-
throw new SQLiteException("Unable to insert " + values + " for " + uri); -
-
-
Uri newUri = ContentUris.withAppendedId(uri, id); -
resolver.notifyChange(newUri, null); -
-
-
-
-
-
从上面传来的参数uri的值为"content://shy.luo.providers.articles/item"。假设当这个函数把数据成功增加到SQLite数据库之后,返回来的id值为n,于是通过调用ContentUris.withAppendedId("content://shy.luo.providers.articles/item", n)得到的newUri的值就为"content://shy.luo.providers.articles/item/n"。这时候就会调用下面语句来通知那些注册了监控"content://shy.luo.providers.articles/item/n"这个URI的ContentObserver,它监控的数据发生变化了: -
resolver.notifyChange(newUri, null);
下面我们就开始分析这个数据变化通知的发送过程,首先来看一下这个过程的时序图,然后再详细分析每一个步骤:
Step 1. ContentResolver.notifyChange
这个函数定义在frameworks/base/core/java/android/content/ContentResolver.java文件中: -
public abstract class ContentResolver { -
-
-
public void notifyChange(Uri uri, ContentObserver observer) { -
notifyChange(uri, observer, true ); -
-
-
public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) { -
-
getContentService().notifyChange( -
uri, observer == null ? null : observer.getContentObserver(), -
observer != null && observer.deliverSelfNotifications(), syncToNetwork); -
} catch (RemoteException e) { -
-
-
-
-
这里调用了ContentService的远接程口来调用它的notifyChange函数来发送数据更新通知。
Step 2. ContentService.notifyChange 这个函数定义在frameworks/base/core/java/android/content/ContentService.java文件中: -
public final class ContentService extends IContentService.Stub { -
-
-
public void notifyChange(Uri uri, IContentObserver observer, -
boolean observerWantsSelfNotifications, boolean syncToNetwork) { -
-
-
-
ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>(); -
synchronized (mRootNode) { -
mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications, -
-
-
final int numCalls = calls.size(); -
for (int i=0; i<numCalls; i++) { -
ObserverCall oc = calls.get(i); -
-
oc.mObserver.onChange(oc.mSelfNotify); -
-
} catch (RemoteException ex) { -
-
-
-
-
-
-
-
-
-
-
这个函数主要做了两件事情,第一件事情是调用ContentService的成员变量mRootNode的collectObserverLocked函数来收集那些注册了监控"content://shy.luo.providers.articles/item/n"这个URI的ContentObserver,第二件事情是分别调用了这些ContentObserver的onChange函数来通知它们监控的数据发生变化了。
Step 3. ObserverNode.collectObserversLocked 这个函数定义在frameworks/base/core/java/android/content/ContentService.java文件中: -
public final class ContentService extends IContentService.Stub { -
-
-
public static final class ObserverNode { -
-
-
private void collectMyObserversLocked(boolean leaf, IContentObserver observer, -
boolean selfNotify, ArrayList<ObserverCall> calls) { -
int N = mObservers.size(); -
IBinder observerBinder = observer == null ? null : observer.asBinder(); -
for (int i = 0; i < N; i++) { -
ObserverEntry entry = mObservers.get(i); -
-
-
-
if (entry.observer.asBinder() == observerBinder && !selfNotify) { -
-
-
-
-
if (leaf || (!leaf && entry.notifyForDescendents)) { -
calls.add(new ObserverCall(this, entry.observer, selfNotify)); -
-
-
-
-
public void collectObserversLocked(Uri uri, int index, IContentObserver observer, -
boolean selfNotify, ArrayList<ObserverCall> calls) { -
-
int segmentCount = countUriSegments(uri); -
if (index >= segmentCount) { -
-
collectMyObserversLocked(true, observer, selfNotify, calls); -
} else if (index < segmentCount){ -
segment = getUriSegment(uri, index); -
-
collectMyObserversLocked(false, observer, selfNotify, calls); -
-
-
int N = mChildren.size(); -
for (int i = 0; i < N; i++) { -
ObserverNode node = mChildren.get(i); -
if (segment == null || node.mName.equals(segment)) { -
-
node.collectObserversLocked(uri, index + 1, observer, selfNotify, calls); -
-
-
-
-
-
-
-
第一次调用collectObserversLocked时,是在mRootNode的这个ObserverNode节点中进行收集ContentObserver的。这时候传进来的uri的值为"content://shy.luo.providers.articles/item/n",index的值为0。调用countUriSegments("content://shy.luo.providers.articles/item/n")函数得到的返回值为3,于是就会调用下面语句: -
segment = getUriSegment("content://shy.luo.providers.articles/item/n",0); -
-
collectMyObserversLocked(false, observer, selfNotify, calls);
这里得到的segment为"shy.luo.providers.articles"。在我们这个情景中,假设mRootNode这个节点中没有注册ContentObserver,于是调用collectMyObserversLocked函数就不会收集到ContentObserver。
在接下来的for循环中,在mRootNode的孩子节点列表mChildren中查找名称等于"shy.luo.providers.articles"的OberverNode节点。在上面分析ContentObserver的注册过程时,我们已经往mRootNode的孩子节点列表mChildren中增加了一个名称为"shy.luo.providers.articles"的OberverNode节点,因此,这里会成功找到它,并且调用它的collectObserversLocked函数来继续收集ContentObserver。 第二次进入到collectObserversLocked函数时,是在名称为"shy.luo.providers.articles"的OberverNode节点中收集ContentObserver的。这时候传来的uri值不变,但是index的值为1,于是执行下面语句: -
segment = getUriSegment("content://shy.luo.providers.articles/item/n",1); -
-
collectMyObserversLocked(false, observer, selfNotify, calls);
这里得到的segment为"item"。在我们这个情景中,我们没有在名称为"shy.luo.providers.articles"的OberverNode节点中注册有ContentObserver,因此这里调用collectMyObserversLocked函数也不会收集到ContentObserver。
在接下来的for循环中,在名称为"shy.luo.providers.articles"的ObserverNode节点的孩子节点列表mChildren中查找名称等于"item"的OberverNode节点。在上面分析ContentObserver的注册过程时,我们已经往名称为"shy.luo.providers.articles"的ObserverNode节点的孩子节点列表mChildren中增加了一个名称为"item"的OberverNode节点,因此,这里会成功找到它,并且调用它的collectObserversLocked函数来继续收集ContentObserver。 第三次进入到collectObserversLocked函数时,是在名称为"shy.luo.providers.articles"的OberverNode节点的子节点中名称为"item"的ObserverNode节点中收集ContentObserver的。这时候传来的uri值不变,但是index的值为2,于是执行下面语句: -
segment = getUriSegment("content://shy.luo.providers.articles/item/n",2); -
-
collectMyObserversLocked(false, observer, selfNotify, calls);
这里得到的segment为"n"。前面我们已经在名称为"shy.luo.providers.articles"的OberverNode节点的子节点中名称为"item"的ObserverNode节点中注册了一个ContentObserver,即ArticlesObserver,因此这里调用collectMyObserversLocked函数会收集到这个ContentObserver。注意,这次调用collectMyObserversLocked函数时,虽然传进去的参数leaf为false,但是由于我们注册ArticlesObserver时,指定了notifyForDescendents参数为true,因此,这里可以把它收集回来。
在接下来的for循环中,继续在该节点的子节点列表mChildren中查找名称等于"n"的OberverNode节点。在我们这个情景中,不存在这个名称为"n"的子节点了,于是收集ContentObserver的工作就结束了,收集结果是只有一个ContentObserver,即我们在前面注册的ArticlesObserver。 返回到Step 2中,调用下面语句来通知相应的ContentObserver,它们监控的数据发生变化了: -
for (int i=0; i<numCalls; i++) { -
ObserverCall oc = calls.get(i); -
-
oc.mObserver.onChange(oc.mSelfNotify); -
-
} catch (RemoteException ex) { -
-
-
前面我们在分析ContentObserver的注册过程的Step 3时,介绍到注册到ContentService服务中的ContentObserver是一个在ContentObserver内部定义的一个类Transport的对象的远程接口,于是这里调用这个接口的onChange函数时,就会进入到ContentObserver的内部类Transport的onChange函数中去。 转载地址:http://hphso.baihongyu.com/