android 中的 ContentObserver (二)
2015-09-28 11:20
465 查看
文章出处:http://blog.csdn.net/shift_wwx/article/details/48782367
请转载的朋友标明出处~~
前一篇博文(android 中的 ContentObserver (一))中利用最近做的项目,简单的说明了一下 ContentObserver 操作过程,这一篇详细的说一下过程。
总结版本基于4.4
在android 中的 ContentObserver (一) 中,提到如果一个db 发生了变化,用户需要最快的知晓。可以做个监听器一直查询db的变化状态,这里需要更正一下,这个不是个好方法,也最好不要想,对于数据表小一点的话,还是可以考虑,可是对于大型的数据表或者字段很多的情况下,这个监听器是没办法做的。
所以,剩下有两种选择,一是选择ContentObserver,另一个选择是广播。
对于两者的区别,大概可以列出下面几点:
一、前者是通过URI来把通知的发送者和接收者关联在一起的,而后者是通过Intent来关联的
二、前者的通知注册中心是由ContentService服务来扮演的,而后者是由ActivityManagerService服务来扮演的
三、前者负责接收数据更新通知的类必须要继承ContentObserver类,而后者要继承BroadcastReceiver类。
从上面这些区别看,两者完全可以做成一个,目前也就是实现的地方不一样而已,其实之所以会有这些区别,主要是因为第四点。
四、Content Proivder组件的数据共享功能本身就是建立在URI的基础之上的,因此专门针对URI来设计另外一套通知机制会更实用和方便,而Android系统的广播机制是一种更加通用的事件通知机制,它的适用范围会更广泛一些。
当然,如果不愿意用 ContentObserver,用广播也是可以,可以将uri 以 param 的形式传递上来。
接下来,根据 source code 来解释一下整个 ContentObserver 的过程
1、注册
在android 中的 ContentObserver (一) 中在Channel list 更新的时候需要通知上层,于是在上面注册了一个 ContentObserver:
其中的三个参数在android 中的 ContentObserver (一) 中也解释过,这里我们结合 Source code来详细看一下。
看一下 ContentResolver 中的registerContentObserver:frameworks/base/core/java/android/content/ContentResolver.java
1) getContentServices()
sContentService 是一个静态成员变量,在sContentService 为null 的时候,会获得前面已经启动起来了的ContentService服务的远程接口,然后把它保存在sContentService变量中。这样,当下次ContentResolver类的getContentService函数再次被调用时,就可以直接把这个ContentService远程接口返回给调用者了。
2)先来看contentService.registerContentObserver中的第三个参数
observer.getContentObserver()
ContentObserver类的getContentObserver函数返回的是一个成员变量mTransport,它的类型为ContentObserver的内部类Transport。从Transport类的定义我们可以知道,它有一个成员变量mContentObserver,用来保存与对应的ContentObserver对象。同时我们还可以看出,ContentObserver类的成员变量mTransport是一个Binder对象,它是要传递给ContentService服务的,以便当ContentObserver所监控的数据发生变化时,ContentService服务可以通过这个Binder对象通知相应的ContentObserver它监控的数据发生变化了。
3)contentService.registerContentObserver
它调用了ContentService类的成员变量mRootNode的addObserverLocked函数来注册这个ContentObserver对象observer。成员变量mRootNode的类型为ContentService在内部定义的一个类ObserverNode。
4)mRootNode.addObserverLocked
从code 上看,可以分为两部分:
一是 mObservers
从code 中可以看到 mObservers 这里添加了所有的 ContentObserver 的远程接口。
二是mChildren
这里存放的是 uri 所有节点。
整理可以知道,如果uri 是content://android.media.tv/channel/1,那么 ObserverNode就可以形成这样的树形:
mRootNode("")
-- ObserverNode("android.media.tv")
-- ObserverNode("channel")
-- ObserverNode("1")
-- [b][b]ObserverEntry("observer")
// “1” 里面的mObservers size 为1[/b][/b]
[b][b]-- ObserverEntry()[/b][/b]
-- ObserverEntry()
-- ObserverEntry()
具体为什么需要在下面继续说明。
注意:这里是通过mRootNode 来做 addObserverLocked() 操作的,里面 mChildren size 是3,mChildren 中每个成员都是ObserverNode 类型,可是这些成员里面
mObservers 却是只有在 index == countUriSegments(uri) 条件成立的时候,那个成员中的mObservers 才会有存在的意义。最终只有在ObserverNode("1")中才是真正注册 observer的地方,即只有ObserverNode("1") 中的 mObservers
才不为 0。
至此,注册的工作就完成了。
2、notifyChange
在android 中的 ContentObserver (一) 中在db 变化的时候,会调用notifyChange来发出数据更新的消息。source code 中参数channelUri 是content://android.media.tv/channel
我们加一层,假如这个uri 是content://android.media.tv/channel/1,也就是id 是1发生更新的时候,发出这样的消息。
1)getContext().getContentResolver().notifyChange(uri, null);
最终会调用getContentService().notifyChange,getContentService前面介绍过,这里不做过多说明。
2)ContentService.notifyChange
这个函数主要做了两件事情,第一件事情是调用ContentService的成员变量mRootNode的collectObserverLocked函数来收集那些注册了监控"content://android.media.tv/channel/1"这个URI的ContentObserver,第二件事情是分别调用了这些ContentObserver的onChange函数来通知它们监控的数据发生变化了。
3)ObserverNode.collectObserversLocked()
第一次index 为0,而segmentCount 的值为3,所以调用的是:
第一次的时候segment 是 android.media.tv,然后调用 collectMyObserversLocked(),但是之前 registerContentObserver 的时候解释过mRootNode 中的mObservers size 是为0,所以,没有搜集到之前注册的 observer。
第二次的时候segment 是 channel,index 的值变成了 1, 然后继续调用的是:
同样,这个时候 ObserverNode 为 “android.media.tv”,里面的 mObservers size 也是为 0,所以也没有搜集到。
第三次的时候segment 是 1,index 的值变成了 2, 然后继续调用的是:
同样,这个时候ObserverNode 为 “channel”,里面的 mObservers size 也是为 0,所以依然没有搜集到。code 继续走的时候,node.collectObserversLocked() 这个时候的node 已经变成了 ObserverNode 为 “1”,这个时候index 变成了 3,所以调用的是:
而它里面的 mObservers 的size 为 1,。看以下的代码,这个时候 for 循环可以执行了,最终调用到了calls.add(),至此 observer 才真正搜集到。
注意:如果上面注册的时候 uri 是 content://android.media.tv/channel 那么这里的 count 是3,而在index 是2的时候就可以找到 observer,所以notifyForDescendants 必须要为true,即 注册函数的第二个参数必须要为true。
至此第 2)步中:
calls 就有了。
注意:如果在别的地方在注册一个 uri(例如是 content://android.media.tv/param),同样的在 mRootNode 下的ObserverNode(""android.media.tv) 下会多一个 ObserverNode("param"),跟ObserverNode("channel") 一样,下面的就一样了。
4)接着第2)步,最后会调用 onChange
这里的mObserver 就是IContentObserver, 而IContentObserver 就是之前在register 的时候observer.getContentObserver() 传进来的。
如果mHandler 为null,就直接调用 onChange(),如果不为空,就通过 NotificationRunnable 来run;
相当于开了一个线程来处理onChange。
5)调用UI 的onChange
至此,ContentObsrver 或说 Content Provider 的共享数据更新通知机制就分析完了。关于ContentProvider 可以看一下:Android基础总结之八:ContentProvider
请转载的朋友标明出处~~
前一篇博文(android 中的 ContentObserver (一))中利用最近做的项目,简单的说明了一下 ContentObserver 操作过程,这一篇详细的说一下过程。
总结版本基于4.4
在android 中的 ContentObserver (一) 中,提到如果一个db 发生了变化,用户需要最快的知晓。可以做个监听器一直查询db的变化状态,这里需要更正一下,这个不是个好方法,也最好不要想,对于数据表小一点的话,还是可以考虑,可是对于大型的数据表或者字段很多的情况下,这个监听器是没办法做的。
所以,剩下有两种选择,一是选择ContentObserver,另一个选择是广播。
对于两者的区别,大概可以列出下面几点:
一、前者是通过URI来把通知的发送者和接收者关联在一起的,而后者是通过Intent来关联的
二、前者的通知注册中心是由ContentService服务来扮演的,而后者是由ActivityManagerService服务来扮演的
三、前者负责接收数据更新通知的类必须要继承ContentObserver类,而后者要继承BroadcastReceiver类。
从上面这些区别看,两者完全可以做成一个,目前也就是实现的地方不一样而已,其实之所以会有这些区别,主要是因为第四点。
四、Content Proivder组件的数据共享功能本身就是建立在URI的基础之上的,因此专门针对URI来设计另外一套通知机制会更实用和方便,而Android系统的广播机制是一种更加通用的事件通知机制,它的适用范围会更广泛一些。
当然,如果不愿意用 ContentObserver,用广播也是可以,可以将uri 以 param 的形式传递上来。
接下来,根据 source code 来解释一下整个 ContentObserver 的过程
1、注册
在android 中的 ContentObserver (一) 中在Channel list 更新的时候需要通知上层,于是在上面注册了一个 ContentObserver:
mContext.getContentResolver().registerContentObserver(Channels.CONTENT_URI, true, mChannelObserver);
其中的三个参数在android 中的 ContentObserver (一) 中也解释过,这里我们结合 Source code来详细看一下。
看一下 ContentResolver 中的registerContentObserver:frameworks/base/core/java/android/content/ContentResolver.java
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 { for (int i = 0; i < 10; i++) { IContentService contentService = getContentService(); if (contentService == null) { //wait for ContentService to be ready SystemClock.sleep(100); continue; } contentService.registerContentObserver(uri, notifyForDescendents, observer.getContentObserver(), userHandle); break; } } catch (RemoteException e) { } }
1) getContentServices()
public static IContentService getContentService() { if (sContentService != null) { return sContentService; } IBinder b = ServiceManager.getService(CONTENT_SERVICE_NAME); if (false) Log.v("ContentService", "default service binder = " + b); sContentService = IContentService.Stub.asInterface(b); if (false) Log.v("ContentService", "default service = " + sContentService); return sContentService; }
sContentService 是一个静态成员变量,在sContentService 为null 的时候,会获得前面已经启动起来了的ContentService服务的远程接口,然后把它保存在sContentService变量中。这样,当下次ContentResolver类的getContentService函数再次被调用时,就可以直接把这个ContentService远程接口返回给调用者了。
2)先来看contentService.registerContentObserver中的第三个参数
observer.getContentObserver()
public IContentObserver getContentObserver() { synchronized (mLock) { if (mTransport == null) { mTransport = new Transport(this); } return mTransport; } }
private static final class Transport extends IContentObserver.Stub { private ContentObserver mContentObserver; public Transport(ContentObserver contentObserver) { mContentObserver = contentObserver; } @Override public void onChange(boolean selfChange, Uri uri, int userId) { ContentObserver contentObserver = mContentObserver; if (contentObserver != null) { contentObserver.dispatchChange(selfChange, uri, userId); } } public void releaseContentObserver() { mContentObserver = null; } }
ContentObserver类的getContentObserver函数返回的是一个成员变量mTransport,它的类型为ContentObserver的内部类Transport。从Transport类的定义我们可以知道,它有一个成员变量mContentObserver,用来保存与对应的ContentObserver对象。同时我们还可以看出,ContentObserver类的成员变量mTransport是一个Binder对象,它是要传递给ContentService服务的,以便当ContentObserver所监控的数据发生变化时,ContentService服务可以通过这个Binder对象通知相应的ContentObserver它监控的数据发生变化了。
3)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"); } 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类的成员变量mRootNode的addObserverLocked函数来注册这个ContentObserver对象observer。成员变量mRootNode的类型为ContentService在内部定义的一个类ObserverNode。
4)mRootNode.addObserverLocked
// 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)) { 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); }
从code 上看,可以分为两部分:
一是 mObservers
private ArrayList<ObserverEntry> mObservers = new ArrayList<ObserverEntry>();
private class ObserverEntry implements IBinder.DeathRecipient { public final IContentObserver observer; public final int uid; public final int pid; public final boolean notifyForDescendants; private final int userHandle; private final Object observersLock; public ObserverEntry(IContentObserver o, boolean n, Object observersLock, int _uid, int _pid, int _userHandle) { this.observersLock = observersLock; observer = o; uid = _uid; pid = _pid; userHandle = _userHandle; notifyForDescendants = n; try { observer.asBinder().linkToDeath(this, 0); } catch (RemoteException e) { binderDied(); } } public void binderDied() { synchronized (observersLock) { removeObserverLocked(observer); } } public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args, String name, String prefix, SparseIntArray pidCounts) { pidCounts.put(pid, pidCounts.get(pid)+1); pw.print(prefix); pw.print(name); pw.print(": pid="); pw.print(pid); pw.print(" uid="); pw.print(uid); pw.print(" user="); pw.print(userHandle); pw.print(" target="); pw.println(Integer.toHexString(System.identityHashCode( observer != null ? observer.asBinder() : null))); } }
从code 中可以看到 mObservers 这里添加了所有的 ContentObserver 的远程接口。
二是mChildren
private ArrayList<ObserverNode> mChildren = new ArrayList<ObserverNode>();
这里存放的是 uri 所有节点。
整理可以知道,如果uri 是content://android.media.tv/channel/1,那么 ObserverNode就可以形成这样的树形:
mRootNode("")
-- ObserverNode("android.media.tv")
-- ObserverNode("channel")
-- ObserverNode("1")
-- [b][b]ObserverEntry("observer")
// “1” 里面的mObservers size 为1[/b][/b]
[b][b]-- ObserverEntry()[/b][/b]
-- ObserverEntry()
-- ObserverEntry()
具体为什么需要在下面继续说明。
注意:这里是通过mRootNode 来做 addObserverLocked() 操作的,里面 mChildren size 是3,mChildren 中每个成员都是ObserverNode 类型,可是这些成员里面
mObservers 却是只有在 index == countUriSegments(uri) 条件成立的时候,那个成员中的mObservers 才会有存在的意义。最终只有在ObserverNode("1")中才是真正注册 observer的地方,即只有ObserverNode("1") 中的 mObservers
才不为 0。
至此,注册的工作就完成了。
2、notifyChange
在android 中的 ContentObserver (一) 中在db 变化的时候,会调用notifyChange来发出数据更新的消息。source code 中参数channelUri 是content://android.media.tv/channel
我们加一层,假如这个uri 是content://android.media.tv/channel/1,也就是id 是1发生更新的时候,发出这样的消息。
1)getContext().getContentResolver().notifyChange(uri, null);
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) { } }
最终会调用getContentService().notifyChange,getContentService前面介绍过,这里不做过多说明。
2)ContentService.notifyChange
public void notifyChange(Uri uri, IContentObserver observer, boolean observerWantsSelfNotifications, boolean syncToNetwork) { notifyChange(uri, observer, observerWantsSelfNotifications, syncToNetwork, UserHandle.getCallingUserId()); }
@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) { 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); } }
这个函数主要做了两件事情,第一件事情是调用ContentService的成员变量mRootNode的collectObserverLocked函数来收集那些注册了监控"content://android.media.tv/channel/1"这个URI的ContentObserver,第二件事情是分别调用了这些ContentObserver的onChange函数来通知它们监控的数据发生变化了。
3)ObserverNode.collectObserversLocked()
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); } int N = mChildren.size(); for (int i = 0; i < N; i++) { ObserverNode node = mChildren.get(i); if (segment == null || node.mName.equals(segment)) { // We found the child, node.collectObserversLocked(uri, index + 1, observer, observerWantsSelfNotifications, targetUserHandle, calls); if (segment != null) { break; } } } }
第一次index 为0,而segmentCount 的值为3,所以调用的是:
segment = getUriSegment(uri, index); // Notify any observers at this level who are interested in descendants collectMyObserversLocked(false, observer, observerWantsSelfNotifications, targetUserHandle, calls);
第一次的时候segment 是 android.media.tv,然后调用 collectMyObserversLocked(),但是之前 registerContentObserver 的时候解释过mRootNode 中的mObservers size 是为0,所以,没有搜集到之前注册的 observer。
第二次的时候segment 是 channel,index 的值变成了 1, 然后继续调用的是:
segment = getUriSegment(uri, index); // Notify any observers at this level who are interested in descendants collectMyObserversLocked(false, observer, observerWantsSelfNotifications, targetUserHandle, calls);
同样,这个时候 ObserverNode 为 “android.media.tv”,里面的 mObservers size 也是为 0,所以也没有搜集到。
第三次的时候segment 是 1,index 的值变成了 2, 然后继续调用的是:
segment = getUriSegment(uri, index); // Notify any observers at this level who are interested in descendants collectMyObserversLocked(false, observer, observerWantsSelfNotifications, targetUserHandle, calls);
同样,这个时候ObserverNode 为 “channel”,里面的 mObservers size 也是为 0,所以依然没有搜集到。code 继续走的时候,node.collectObserversLocked() 这个时候的node 已经变成了 ObserverNode 为 “1”,这个时候index 变成了 3,所以调用的是:
collectMyObserversLocked(true, observer, observerWantsSelfNotifications, targetUserHandle, calls);
而它里面的 mObservers 的size 为 1,。看以下的代码,这个时候 for 循环可以执行了,最终调用到了calls.add(),至此 observer 才真正搜集到。
注意:如果上面注册的时候 uri 是 content://android.media.tv/channel 那么这里的 count 是3,而在index 是2的时候就可以找到 observer,所以notifyForDescendants 必须要为true,即 注册函数的第二个参数必须要为true。
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++) { 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)) { calls.add(new ObserverCall(this, entry.observer, selfChange)); } } } }
至此第 2)步中:
ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
calls 就有了。
注意:如果在别的地方在注册一个 uri(例如是 content://android.media.tv/param),同样的在 mRootNode 下的ObserverNode(""android.media.tv) 下会多一个 ObserverNode("param"),跟ObserverNode("channel") 一样,下面的就一样了。
4)接着第2)步,最后会调用 onChange
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); } }
这里的mObserver 就是IContentObserver, 而IContentObserver 就是之前在register 的时候observer.getContentObserver() 传进来的。
public abstract class ContentObserver { ...... private static final class Transport extends IContentObserver.Stub { ContentObserver mContentObserver; ...... public void onChange(boolean selfChange) { ContentObserver contentObserver = mContentObserver; if (contentObserver != null) { contentObserver.dispatchChange(selfChange); } } ...... } ...... }
@Deprecated public final void dispatchChange(boolean selfChange) { dispatchChange(selfChange, null); }
public final void dispatchChange(boolean selfChange, Uri uri) { dispatchChange(selfChange, uri, UserHandle.getCallingUserId()); }
private void dispatchChange(boolean selfChange, Uri uri, int userId) { if (mHandler == null) { onChange(selfChange, uri, userId); } else { mHandler.post(new NotificationRunnable(selfChange, uri, userId)); } }
如果mHandler 为null,就直接调用 onChange(),如果不为空,就通过 NotificationRunnable 来run;
private final class NotificationRunnable implements Runnable { private final boolean mSelfChange; private final Uri mUri; private final int mUserId; public NotificationRunnable(boolean selfChange, Uri uri, int userId) { mSelfChange = selfChange; mUri = uri; mUserId = userId; } @Override public void run() { ContentObserver.this.onChange(mSelfChange, mUri, mUserId); } }
相当于开了一个线程来处理onChange。
5)调用UI 的onChange
private final class ChannelObserver extends ContentObserver { public ChannelObserver() { super(new Handler()); } @Override public void onChange(boolean selfChange, Uri uri) { updateChannelList(); } @Override public IContentObserver releaseContentObserver() { // TODO Auto-generated method stub return super.releaseContentObserver(); } }
至此,ContentObsrver 或说 Content Provider 的共享数据更新通知机制就分析完了。关于ContentProvider 可以看一下:Android基础总结之八:ContentProvider
相关文章推荐
- Android CheckBox 图片设置开关
- Android签名打包出现Export aborted because fatal lint errors were found的解决
- 保护Android代码(防止反编译)
- Android Monkey测试脚本
- android 双击退出应用
- Android 静态分析smail
- android混淆
- Android内容提供者(Content provider)
- Android学习路径(两)项目文件本身使用场景和文件演示
- android性能问题
- android手机刷机教程指南
- Android项目Tab类型主界面大总结
- Android Fragment 你应该知道的一切
- androidの自定义控件View在Activity中使用findByViewId得到结果为null,解决方法。。
- [转]Android应用自动更新功能的代码实现
- Android Fragment 真正的完全解析(下)
- Android Fragment 真正的完全解析(上)
- android 短信验证码自动填写的两种方式
- Android savedInstanceState的使用
- Android自适应不同分辨率或不同屏幕大小