前言
相信大家在对数据库进行操作的代码中经常看到:
cursor.setNotificationUri(getContext().getContentResolver(), uri);
getContext().getContentResolver().notifyChange(uri, null);
今天,我们就来具体讲一下这两行代码的具体作用
观察者一
setNotificationUri 的流程
AbstractCursor.setNotificationUri
AbstractCursor 是接口 Cursor 的实现类
@Override
public void setNotificationUri(ContentResolver cr, Uri notifyUri) {
setNotificationUri(cr, notifyUri, UserHandle.myUserId());
}
/** @hide - set the notification uri but with an observer for a particular user's view */
public void setNotificationUri(ContentResolver cr, Uri notifyUri, int userHandle) {
synchronized (mSelfObserverLock) {
mNotifyUri = notifyUri;
mContentResolver = cr;
if (mSelfObserver != null) {
mContentResolver.unregisterContentObserver(mSelfObserver);
}
// SelfContentObserver 是 AbstractCursor 的一个内部类
mSelfObserver = new SelfContentObserver(this);
// 可以看到这是最主要的操作
mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver, userHandle);
mSelfObserverRegistered = true;
}
}
ContentResolver.registerContentObserver
/** @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) {
}
}
ContentService.registerContentObserver
@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");
}
...
synchronized (mRootNode) {
// 这里是我们此行的主要操作,mRootNode 为 ObserverNode 的实例
mRootNode.addObserverLocked(uri, observer, notifyForDescendants, mRootNode,
uid, pid, userHandle);
if (false) Log.v(TAG, "Registered observer " + observer + " at " + uri +
" with notifyForDescendants " + notifyForDescendants);
}
}
ContentService.java :: ObserverNode
// Invariant: userHandle is either a hard user number or is USER_ALL
public void addObserverLocked(Uri uri, IContentObserver observer,
boolean notifyForDescendants, Object observersLock,
int uid, int pid, int userHandle) {
addObserverLocked(uri, 0, observer, notifyForDescendants, observersLock,
uid, pid, userHandle);
}
private void addObserverLocked(Uri uri, int index, IContentObserver observer,
boolean notifyForDescendants, Object observersLock,
int uid, int pid, int userHandle) {
// If this is the leaf node add the observer
if (index == countUriSegments(uri)) {
// 添加一个 ObserverEntry 到 mObservers 中,mObservers 为 ObserverNode 的私有成员变量
mObservers.add(new ObserverEntry(observer, notifyForDescendants, observersLock,
uid, pid, userHandle));
return;
}
// Look to see if the proper child already exists
String segment = getUriSegment(uri, index);
if (segment == null) {
throw new IllegalArgumentException("Invalid Uri (" + uri + ") used for observer");
}
int N = mChildren.size();
for (int i = 0; i < N; i++) {
ObserverNode node = mChildren.get(i);
if (node.mName.equals(segment)) {
node.addObserverLocked(uri, index + 1, observer, notifyForDescendants,
observersLock, uid, pid, userHandle);
return;
}
}
// No child found, create one
ObserverNode node = new ObserverNode(segment);
mChildren.add(node);
node.addObserverLocked(uri, index + 1, observer, notifyForDescendants,
observersLock, uid, pid, userHandle);
}
notifyChange 的流程
ContentResolver.notifyChange
public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer) {
notifyChange(uri, observer, true /* sync to network */);
}
public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer,
boolean syncToNetwork) {
Preconditions.checkNotNull(uri, "uri");
notifyChange(
ContentProvider.getUriWithoutUserId(uri),
observer,
syncToNetwork,
ContentProvider.getUserIdFromUri(uri, UserHandle.myUserId()));
}
public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork,
int userHandle) {
try {
// 到服务端去 notifyChange
getContentService().notifyChange(
uri, observer == null ? null : observer.getContentObserver(),
observer != null && observer.deliverSelfNotifications(), syncToNetwork,
userHandle);
} catch (RemoteException e) {
}
}
ContentService.notifyChange
@Override
public void notifyChange(Uri uri, IContentObserver observer,
boolean observerWantsSelfNotifications, boolean syncToNetwork,
int userHandle) {
...
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) {
...
}
}
...
} finally {
restoreCallingIdentity(identityToken);
}
}
ContentService.java :: ObserverNode
public void collectObserversLocked(Uri uri, int index, IContentObserver observer,
boolean observerWantsSelfNotifications, int targetUserHandle,
ArrayList<ObserverCall> calls) {
String segment = null;
int segmentCount = countUriSegments(uri);
if (index >= segmentCount) {
// This is the leaf node, notify all observers
collectMyObserversLocked(true, observer, observerWantsSelfNotifications,
targetUserHandle, calls);
} else if (index < segmentCount){
segment = getUriSegment(uri, index);
// Notify any observers at this level who are interested in descendants
collectMyObserversLocked(false, observer, observerWantsSelfNotifications,
targetUserHandle, calls);
}
...
}
private void collectMyObserversLocked(boolean leaf, IContentObserver observer,
boolean observerWantsSelfNotifications, int targetUserHandle,
ArrayList<ObserverCall> calls) {
int N = mObservers.size();
IBinder observerBinder = observer == null ? null : observer.asBinder();
for (int i = 0; i < N; i++) {
// 提取出 mObservers 中的 ObserverEntry
ObserverEntry entry = mObservers.get(i);
// Don't notify the observer if it sent the notification and isn't interested
// in self notifications
boolean selfChange = (entry.observer.asBinder() == observerBinder);
if (selfChange && !observerWantsSelfNotifications) {
continue;
}
// Does this observer match the target user?
if (targetUserHandle == UserHandle.USER_ALL
|| entry.userHandle == UserHandle.USER_ALL
|| targetUserHandle == entry.userHandle) {
// Make sure the observer is interested in the notification
if (leaf || (!leaf && entry.notifyForDescendants)) {
// 用 ObserverEntry 构造 ObserverCall 添加到 calls 中
calls.add(new ObserverCall(this, entry.observer, selfChange));
}
}
}
}
ContentService.java :: ObserverCall
public static final class ObserverCall {
final ObserverNode mNode;
final IContentObserver mObserver;
final boolean mSelfChange;
ObserverCall(ObserverNode node, IContentObserver observer, boolean selfChange) {
mNode = node;
mObserver = observer;
mSelfChange = selfChange;
}
}
小结
由此可知,ContentService.notifyChange 中最重要的是:
oc.mObserver.onChange(oc.mSelfChange, uri, userHandle);
- 其调用 ObserverCall 中的 mObserver 的 onChange 方法,而 ObserverCall 中的的 mObserver 其实来源于 ObserverNode 的成员变量 mObservers 中的 ObserverEntry
- 而 setNotificationUri 实际上用 SelfContentObserver 实例 mSelfObserver 构造了一个 ObserverEntry 放入了 ObserverNode 的成员变量 mObservers 中
- 到此,观察者一就讲述完了,实际上就是由 notifyChange(uri, null) 通知相应的 uri 观察者内容有变,然后调用观察者的 onChange 方法
观察者二
AbstractCursor :: SelfContentObserver
/**
* Cursors use this class to track changes others make to their URI.
*/
protected static class SelfContentObserver extends ContentObserver {
WeakReference<AbstractCursor> mCursor;
public SelfContentObserver(AbstractCursor cursor) {
super(null);
mCursor = new WeakReference<AbstractCursor>(cursor);
}
...
@Override
public void onChange(boolean selfChange) {
AbstractCursor cursor = mCursor.get();
if (cursor != null) {
// 调用 Cursor 的 onChange
// setNotificationUri 时,mSelfObserver = new SelfContentObserver(this);
cursor.onChange(false);
}
}
}
AbstractCursor.onChange
/**
* Subclasses must call this method when they finish committing updates to notify all
* observers.
*
* @param selfChange
*/
protected void onChange(boolean selfChange) {// 此时,selfChange = false
synchronized (mSelfObserverLock) {
// 执行此处
// 通知所有注册的观察者
mContentObservable.dispatchChange(selfChange, null);
if (mNotifyUri != null && selfChange) {
mContentResolver.notifyChange(mNotifyUri, mSelfObserver);
}
}
}
ContentObservable.dispatchChange
public void dispatchChange(boolean selfChange, Uri uri) {
synchronized(mObservers) {
for (ContentObserver observer : mObservers) {
if (!selfChange || observer.deliverSelfNotifications()) {
observer.dispatchChange(selfChange, uri);
}
}
}
}
等等,这里为啥又出来了一个 mObservers?他们是观察什么的?
Observable.mObservers
public abstract class Observable<T> {
protected final ArrayList<T> mObservers = new ArrayList<T>();
public void registerObserver(T observer) {
}
public void unregisterObserver(T observer) {
}
public void unregisterAll() {
}
查看他们的调用可以发现:
AbstractCursor.java
public void registerContentObserver(ContentObserver observer) {
mContentObservable.registerObserver(observer);
}
...
@Override
public void unregisterContentObserver(ContentObserver observer) {
if (!mClosed) {
mContentObservable.unregisterObserver(observer);
}
}
也就是说 mObservers 中其实是调用 AbstractCursor.registerContentObserver(ContentObserver observer) 注册的观察者 observer,到此处,第二个观察者就很明显了
ContentObserver.java
private void dispatchChange(boolean selfChange, Uri uri, int userId) {
if (mHandler == null) {
onChange(selfChange, uri, userId);
} else {
mHandler.post(new NotificationRunnable(selfChange, uri, userId));
}
}
// 此方法就是上面注册的 observer 需要 override 的
public void onChange(boolean selfChange) {
// Do nothing. Subclass should override.
}
总结
本文介绍了两种观察者,他们之间稍有不同:
cursor.setNotificationUri(getContext().getContentResolver(), uri);
这里是注册一个观察者,其监听 uri 代表内容的变化(我们需要调用 getContext().getContentResolver().notifyChange(uri, null) 才能通知观察者 uri 代表的内容发生了变化),注册的观察者是 AbstractCursor 的内部类 SelfContentObserver
监听到变化时,其会调用 this 的 onChange 方法,进而通知第二个观察者
public void dispatchChange(boolean selfChange, Uri uri) {
synchronized(mObservers) {
for (ContentObserver observer : mObservers) {
if (!selfChange || observer.deliverSelfNotifications()) {
observer.dispatchChange(selfChange, uri);
}
}
}
}
这里的观察者 mObservers 是由 AbstractCursor.registerContentObserver(ContentObserver observer) 注册的
并不十分准确地总结来说:
* 第一个观察者监听的是 uri 代表内容的变化,第二个观察者监听的是第一个观察者监听到变化这件事
* 因此,如果不注册第一个观察者,即便注册了第二个观察者,也监听不到变化