Cursor 中的观察者模式

前言

相信大家在对数据库进行操作的代码中经常看到:

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 代表内容的变化,第二个观察者监听的是第一个观察者监听到变化这件事
* 因此,如果不注册第一个观察者,即便注册了第二个观察者,也监听不到变化

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值