Android(安卓)System Server大纲之ContentService和ContentProvider原理剖析
Android System Server大纲之ContentService和ContentProvider原理剖析
内容提供程序
观察内容提供商
- Android System Server大纲之ContentService和ContentProvider原理剖析
- 前言
- APP发起查询
- 深入ContentResolver
- 准备工作
- 获取ContentProvider
- 公布ContentProvider
- 关系图
- ContentProvider数据监听
- 观察者注册过程
- 数据变化通知过程
- 总结
前言
ContentService是Android四大组件之一的ContentProvider密切相关的一个系统服务,且和AccountManagerService也有着紧密的联系。ContentService以功能来划分,就两大模块:
- 提供管理通知监听ContentProvider数据变化的观察者的服务
- 同步功能:同步日历、Email等
第一个功能,对于很多开发者来说可能熟悉。而对于第二个,可能就会陌生一点,这个是Android提供的同步功能,很多APP开发者,也很难用到这个Android的同步功能。ContentService的同步功能和AccountManagerService往往紧密联系在一起。本文将不再阐述ContentService的同步功能,有兴趣的读者可以自行阅读Android的参考文档了解该功能的使用方法https://developer.android.google.cn/reference/android/content/SyncRequest.html。那么本文将阐述的内容是:
- ContentProvider的原理
- ContentProvider的观察者服务
ContentProvider是Android的四大组件之一,是提供APP间安全共享数据的方式之一,APP可以通过ContentProvider从其它APP中获取到想要的数据,例如读取手机的联系人。也可以通过ContentProvider把APP的数据共享出去给其它APP使用。
以查询ContentProvider的数据的流程为线索,一步一步分析这个过程,从而了解ContentProvider的过程和原理。
APP发起查询
引用官方的一段话:如果您想要访问内容提供程序中的数据,可以将应用的 Context 中的 ContentResolver 对象用作客户端来与提供程序通信。 ContentResolver 对象会与提供程序对象(即实现 ContentProvider 的类实例)通信。 提供程序对象从客户端接收数据请求,执行请求的操作并返回结果。
APP发起查询,很简单,如下:
ContentResolver cr = getContentResolver();cr.query(Uri uri, ....);
首先通过getContentResolver()获取到ContentResolver对象,ContentResolver对象好比内容分解器,能够分解出来需要调用哪个内容提供程序即ContentProvider。ContentResolver分解的依据便是参数Uri。Uri是如何把ContentResolver和ContentProvider联系起来的呢?Uri可以看作是一个地址描述,随意举一个Uri可描述的地址例子:
content://user_dictionary
可以和平时上网的网址做一个类比,如访问百度:
https://www.baidu.com
Uri和网址结构有很大相似性,https表示的是网络技术中的传输协议,那么content也可以当做ContentProvider中的一种协议,那么content就代表当前需要通过ContentProvider进行数据通信。www.baidu.com是百度的域名,表示需要访问网站的位置,user_dictionary也就可以比作ContentProvider的域名,user_dictionary表示是那个ContentProvider。换句话说,ContentResolver接收到content://user_dictionary这个Uri时,就知道当前需要发起ContentProvider数据交互,通过user_dictionary可以寻找用user_dictionary表示的ContentProvider。
深入ContentResolver
准备工作
查看ContentResolver的定义,如下:
public abstract class ContentResolver { ......}
可见ContentResolver是一个抽象类,所以说getContentResolver()所获取到实例本质是ContentResolver的子类,查看getContentResolver()的具体实现:
private final ApplicationContentResolver mContentResolver;public ContentResolver getContentResolver() { return mContentResolver;}
上面的代码定义在文件frameworks/base/core/java/android/app/ContextImpl.java中
从上面的代码可知,getContentResolver()获取到的实际是ApplicationContentResolver的实例mContentResolver。cr.query(Uri uri, ….)的实现如下:
public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri,......) { IContentProvider unstableProvider = acquireUnstableProvider(uri); ...... IContentProvider stableProvider = null; Cursor qCursor = null; try { ...... try { qCursor = unstableProvider.query(mPackageName, uri, projection, selection, selectionArgs, sortOrder, remoteCancellationSignal); } catch (DeadObjectException e) { unstableProviderDied(unstableProvider); stableProvider = acquireProvider(uri); if (stableProvider == null) { return null; } qCursor = stableProvider.query(mPackageName, uri, projection, selection, selectionArgs, sortOrder, remoteCancellationSignal); } if (qCursor == null) { return null; } ......}
这个方法定义在文件frameworks/base/core/java/android/content/ContentResolver.java中。
这里用文字描述一下上面代码的过程,先声明两个相同类型的局部变量unstableProvider、stableProvider,都是IContentProvider的实例,IContentProvider是AIDL的接口,所以IContentProvider所调用的方法是远程调用。通过acquireUnstableProvider()方法给unstableProvider变量赋值,unstableProvider调用query()方法,如果发生DeadObjectException异常,调用acquireProvider()方法给stableProvider赋值,然后调用stableProvider的query()方法。
这里有点奇怪,为什么要声明两个一样的IContentProvider变量,且调用相同的方法query()。从变量的命名上,也能找到一点线索,unstableProvider和stableProvider,前者是不稳定的provider,后者是稳定的provider。什么样表示稳定的,什么样表示不稳定的?从上面的代码来看,不稳定的provider,调用query()方法会抛出DeadObjectException。下面先看看unstableProvider的赋值过程:
public final IContentProvider acquireExistingProvider(......) { synchronized (mProviderMap) { final ProviderKey key = new ProviderKey(auth, userId); final ProviderClientRecord pr = mProviderMap.get(key); if (pr == null) { return null; } IContentProvider provider = pr.mProvider; IBinder jBinder = provider.asBinder(); ...... return provider; }}
这个方法定义在文件frameworks/base/core/java/android/app/ActivityThread.java中。
可见unstableProvider是从变量mProviderMap的实例中遍历出来,也就是说,在调用者的进程内部,对provider会缓存到mProviderMap这个变量中。而IContentProvider是一个跨进程的远程调用。换句话说,调用者的进程内部所缓存的unstableProvider实例所对应的远程进程不能保证还正常运行着,如果所对应的远程进程没有运行,那么就会抛出DeadObjectException异常,并调用unstableProviderDied()方法把本地的缓存清除。然后通过acquireProvider()重新生产一个新的stableProvider,且Android系统会启动和stableProvider对应的远程进程,这个过程下文会阐述。可见Android这个举措是为了性能考虑,目的让APP的运行仅可能的快。
获取ContentProvider
回到上文中实例化变量unstableProvider和stableProvider的代码,unstableProvider或stableProvider实例化后,直接调用query()方法,然后直接就可以返回Cursor给调用者了,说明在这里的query()这一步,已经拿到调用者需要的数据。所以理解unstableProvider和stableProvider的实质至关重要。那么unstableProvider和stableProvider所对应的远程进程的服务是哪一个呢?是不是就直接对应ContentProvider呢?
由于unstableProvider是一个调用者进程中缓存的实例,所以需要对stableProvider下手,了解stableProvider的实例化过程即可,如下:
public final IContentProvider acquireProvider(......) { ...... IActivityManager.ContentProviderHolder holder = null; try { holder = ActivityManagerNative.getDefault().getContentProvider( getApplicationThread(), auth, userId, stable); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } ...... return holder.provider;}
这个方法定义在文件frameworks/base/core/java/android/app/ActivityThread.java中。
stableProvider被封装到ContentProviderHolder的变量中provider中。通过调用ActivityManagerNative.getContentProvider()获取ContentProviderHolder,ActivityManagerNative的所对应的远程服务是system_process中的ActivityManagerService,接着看getContentProvider()这个方法:
public final ContentProviderHolder getContentProvider( IApplicationThread caller, String name, int userId, boolean stable) { ...... return getContentProviderImpl(caller, name, null, stable, userId);}
这个方法定义在文件frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java中。
这里直接调用了getContentProviderImpl()方法:
private ContentProviderHolder getContentProviderImpl(IApplicationThread caller, String name, IBinder token, boolean stable, int userId) { ContentProviderRecord cpr; ContentProviderConnection conn = null; synchronized(this) { ...... boolean providerRunning = cpr != null && cpr.proc != null && !cpr.proc.killed; if (providerRunning) { ...... } if (!providerRunning) { ...... // If the provider is not already being launched, then get it // started. if (i >= N) { try { // Content provider is now in use, its package can't be stopped. ...... if (proc != null && proc.thread != null && !proc.killed) { ...... } else { proc = startProcessLocked(cpi.processName, cpr.appInfo, false, 0, "content provider", new ComponentName(cpi.applicationInfo.packageName, cpi.name), false, false, false); ...... } cpr.launchingApp = proc; mLaunchingProviders.add(cpr); } finally { Binder.restoreCallingIdentity(origId); } } ...... mProviderMap.putProviderByName(name, cpr); conn = incProviderCountLocked(r, cpr, token, stable); if (conn != null) { conn.waiting = true; } } } // Wait for the provider to be published... synchronized (cpr) { while (cpr.provider == null) { ...... cpr.wait(); ...... } } return cpr != null ? cpr.newHolder(conn) : null;}
这个方法定义在文件frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java中。
由于这个方法的代码篇幅非常大,这里省略了很多代码,省略的代码主要就是一些缓存、权限等等相关的代码。这里假设provider的进程没有启动,从最原始,最干净的时候分析ContentProvider的这个过程。聚焦上面的代码,首先分两种情况,providerRunning和!providerRunning,providerRunning是基于!providerRunning为前提的,因此provider第一次启动是运行!providerRunning这个代码路径。假若provider没有运行过,Android首先通过startProcessLocked()把provider所在的应用启动起来,这个过程这里暂时先放下,继续往下看,在最后面,有一个while循环,循环条件是cpr.provider == null?这里会一直等待cpr的provider变量被赋值,回到上文中的acquireProvider()方法的代码,acquireProvider()首先要获取的是ContentProviderHolder的实例,上面的代码如果cpr != null,就返回一个ContentProviderHolder对象(cpr.newHolder(conn))。所以这里的cpr.provider就是上文中acquireProvider()需要获取的IContentProvider的实例对象。
公布ContentProvider
因此,只要继续分析清楚cpr.provider的赋值过程,就知道开始的时候ContentResolver.query()所调用的真正的远程服务。回到上面的代码,startProcessLocked()启动应用时,运行到如下代码(APP的启动过程本文不再赘述):
public static void main(String[] args) { ...... Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); ......}
这个方法定义在文件frameworks/base/core/java/android/app/ActivityThread.java中。
生成ActivityThread实例,也就是常说的主线程(UI线程了),然后调用attach()方法:
private void attach(boolean system) { ...... final IActivityManager mgr = ActivityManagerNative.getDefault(); try { mgr.attachApplication(mAppThread); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } ......}
这个方法定义在文件frameworks/base/core/java/android/app/ActivityThread.java中。
又回到ActivityManagerService了,接着往下看:
public final void attachApplication(IApplicationThread thread) { ...... attachApplicationLocked(thread, callingPid); ......}
这个方法定义在文件frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java中。
这里没有需要看的代码,继续往下跟踪:
private final boolean attachApplicationLocked(IApplicationThread thread,.....) { List providers = normalMode ? generateApplicationProvidersLocked(app) : null; thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,......);}
这个方法定义在文件frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java中。
IApplicationThread实例thread是远程APP的远程调用端,所以thread.bindApplication()实际又从system_process进程回到了APP所在的进程,注意第三个参数providers,providers是封装了应用的所有的ContentProvider,详情读者可以阅读generateApplicationProvidersLocked(app)方法,本文不再阐述。继续往下看:
public final void bindApplication(String processName, ApplicationInfo appInfo, List providers, ComponentName instrumentationName,......) { ...... data.providers = providers; data.compatInfo = compatInfo; data.initProfilerInfo = profilerInfo; sendMessage(H.BIND_APPLICATION, data);}
这个方法定义在文件frameworks/base/core/java/android/app/ActivityThread.java中。
发送了一个H.BIND_APPLICATION的消息,注意data.providers = providers。该消息的处理是在:
private void handleBindApplication(AppBindData data) {if (!data.restrictedBackupMode) { if (!ArrayUtils.isEmpty(data.providers)) { installContentProviders(app, data.providers); ...... }}
这个方法定义在文件frameworks/base/core/java/android/app/ActivityThread.java中。
调用了installContentProviders()方法,注意参数data.providers,如下:
private void installContentProviders( Context context, List providers) { final ArrayList results = new ArrayList(); for (ProviderInfo cpi : providers) { IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi, false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/); if (cph != null) { cph.noReleaseNeeded = true; results.add(cph); } } try { ActivityManagerNative.getDefault().publishContentProviders( getApplicationThread(), results); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); }}
这个方法定义在文件frameworks/base/core/java/android/app/ActivityThread.java中。
把应用的所有的ContentProvider信息封装到ContentProviderHolder中,这里要回到上文中acquireProvider()方法,获取IContentProvider的实例正好是ContentProviderHolder的中的变量provider,因此,这里需要了解上面代码ContentProviderHolder的实例cph的实例化过程,看installProvider()方法:
private IActivityManager.ContentProviderHolder installProvider(Context context, IActivityManager.ContentProviderHolder holder, ProviderInfo info,.....) { ContentProvider localProvider = null; IContentProvider provider; if (holder == null || holder.provider == null) { ...... try { final java.lang.ClassLoader cl = c.getClassLoader(); localProvider = (ContentProvider)cl. loadClass(info.name).newInstance(); provider = localProvider.getIContentProvider(); ...... IActivityManager.ContentProviderHolder retHolder; synchronized (mProviderMap) { IBinder jBinder = provider.asBinder(); if (localProvider != null) { ComponentName cname = new ComponentName(info.packageName, info.name); ProviderClientRecord pr = mLocalProvidersByName.get(cname); if (pr != null) { ...... } else { holder = new IActivityManager.ContentProviderHolder(info); holder.provider = provider; ...... } retHolder = pr.mHolder; } else { ...... return retHolder;}
这个方法定义在文件frameworks/base/core/java/android/app/ActivityThread.java中。
上面的代码通过ClassLoader映射ContentProvider的对象实例,然后调用getIContentProvider()方法,获取到IContentProvider的实例provider,然后赋值给ContentProviderHolder的实例holder的变量provider,所以provider正是acquireProvider()中获取的的IContentProvider的实例,而继续看getIContentProvider()方法查看provider的本质是:
......private Transport mTransport = new Transport();public IContentProvider getIContentProvider() { return mTransport;}class Transport extends ContentProviderNative { public Cursor query(.....){ ...... } ......}......
这个代码定义在文件frameworks/base/core/java/android/content/ContentProvider.java中。
上面的代码可见,provider实质是Transport的实例mTransport,Transport是ContentProviderNative的子类,而ContentProviderNative是IContentProvider的子类。
下面继续看看provider和ActivityManagerService的关系,回到上文中的installContentProviders()方法,调用了publishContentProviders()方法,如下:
public final void publishContentProviders(IApplicationThread caller, List providers) { ...... final int N = providers.size(); for (int i = 0; i < N; i++) { ContentProviderHolder src = providers.get(i); if (src == null || src.info == null || src.provider == null) { continue; } ContentProviderRecord dst = r.pubProviders.get(src.info.name); if (DEBUG_MU) Slog.v(TAG_MU, "ContentProviderRecord uid = " + dst.uid); if (dst != null) { ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name); mProviderMap.putProviderByClass(comp, dst); String names[] = dst.info.authority.split(";"); for (int j = 0; j < names.length; j++) { mProviderMap.putProviderByName(names[j], dst); } ...... synchronized (dst) { dst.provider = src.provider; dst.proc = r; dst.notifyAll(); } } }}
这个代码定义在文件frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java中。
把应用的ContentProvider信息缓存到mProviderMap中,这里重点关注语句dst.provider = src.provider,回到上文中getContentProviderImpl()方法中的代码,后面的while循环,等待cpr.provider的赋值,dst.provider = src.provider正好就是这个赋值过程,cpr.provider赋值后,getContentProviderImpl()返回ContentProviderHolder的实例cpr.newHolder(conn),而这个实例持有变量provider指向Transport的实例mTransport,也就是应用的ContentProvider。
关系图
这个过程非常绕乱人的头绪,下面把这个过程简单转换成一张简单的关系图,理清这个过程和关系,如下:
ContentProvider数据监听
观察者注册过程
有时APP开发的时候,APP运行时,需要实时监听一些ContentProvider数据的变化。如用户添加了一个联系人,APP需要接收到联系人添加的通知。由于ContentProvider的提供者,和需求者不是同一个APP,所以,这个通知的纽带,就需要ContentService来完成。从注册一个观察者开始,分析这个通知的来龙去脉,注册代码如下:
ContentResolver cr = getContentResolver();cr.registerContentObserver(@NonNull Uri uri, boolean notifyForDescendants, @NonNull ContentObserver observer);
当ContentProvider的数据发生变化时,便会回调到ContentObserver的onChange()方法,观察者ContentObserver observer被注册到哪里去呢?继续进入分析:
public final void registerContentObserver(Uri uri, boolean notifyForDescendents, ContentObserver observer, @UserIdInt int userHandle) { try { getContentService().registerContentObserver(uri, notifyForDescendents, observer.getContentObserver(), userHandle); } catch (RemoteException e) { }}
这个方法定义在文件frameworks/base/core/java/android/content/ContentResolver.java中。
上面的代码getContentService()获取到的对象是:
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;}
这个方法定义在文件frameworks/base/core/java/android/content/ContentResolver.java中。
阅读《Android系统之System Server大纲 》可知,启动的CONTENT_SERVICE_NAME的系统服务如下:
private static final String CONTENT_SERVICE_CLASS = "com.android.server.content.ContentService$Lifecycle";traceBeginAndSlog("StartContentService");mSystemServiceManager.startService(CONTENT_SERVICE_CLASS);Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
这个方法定义在文件frameworks/base/services/java/com/android/server/SystemServer.java中。
所以getContentService()获取到的是ContentService,继续往下分析registerContentObserver():
public void registerContentObserver(Uri uri, boolean notifyForDescendants, IContentObserver observer, int userHandle) { ...... synchronized (mRootNode) { mRootNode.addObserverLocked(uri, observer, notifyForDescendants, mRootNode, uid, pid, userHandle); if (false) Log.v(TAG, "Registered observer " + observer + " at " + uri + " with notifyForDescendants " + notifyForDescendants); }}
这个方法定义在文件frameworks/base/services/core/java/com/android/server/content/ContentService.java中。
上面的代码把观察者observer通过addObserverLocked放置在mRootNode对象中
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); 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); }
这个方法定义在文件frameworks/base/services/core/java/com/android/server/content/ContentService.java中。
首先把观察者observer再次封装到mObservers中,mObservers是ArrayList的实例,后面依次遍历整个需要监听的Uri,用segment生产一个ObserverNode实例,保存在ArrayList的实例mChildren中。
观察者都被封装好以后,就等待数据的变化了。在上文ContentProvider的原理中,可知,ContentProvider的需求者拿到ContentProvider提供者的远程调用后,两个APP直接进行交互了,任何数据变化并没有经过ContentService,因此,ContentService是如何监测ContentProvider数据发生变化并通知到观察者呢?这里的机制便是ContentProvider提供者的数据发生变化时,ContentProvider提供者必须主动通过notifyChange()方法通知ContentService数据发生了变化。下面以联系人的数据库变化为例,阐述这个过程。
数据变化通知过程
添加一个联系人,调用ContactsProvider的insert()方法,如下:
public Uri insert(Uri uri, ContentValues values) { incrementStats(mInsertStats, mInsertInBatchStats); ContactsTransaction transaction = startTransaction(false); try { Uri result = insertInTransaction(uri, values); if (result != null) { transaction.markDirty(); } transaction.markSuccessful(false); return result; } finally { endTransaction(false); }}
这个方法定义在文件packages/providers/ContactsProvider/src/com/android/providers/contacts/AbstractContactsProvider.java中。
上面的代码中,一次插入的业务抽象成一个ContactsTransaction,然后调用insertInTransaction()方法把数据插入数据库成功后,调用transaction.markDirty()标记当前的数据状态有变化,然后调用endTransaction()结束当前的业务。如下:
private void endTransaction(boolean callerIsBatch) { ContactsTransaction transaction = mTransactionHolder.get(); if (transaction != null && (!transaction.isBatch() || callerIsBatch)) { boolean notify = false; try { if (transaction.isDirty()) { notify = true; } transaction.finish(callerIsBatch); if (notify) { notifyChange(); } } finally { // No matter what, make sure we clear out the thread-local transaction reference. mTransactionHolder.set(null); } }}
这个方法定义在文件packages/providers/ContactsProvider/src/com/android/providers/contacts/AbstractContactsProvider.java中。
上面的代码,通过mTransactionHolder.get()获取刚刚进行的业务transaction,如果的这个业务被标记为markDirty(),transaction.isDirty()返回true,所以notify被置成true,所以会调用notifyChange()。往下看这个方法:
protected void notifyChange(boolean syncToNetwork, boolean syncToMetadataNetwork) { getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null, syncToNetwork); getContext().getContentResolver().notifyChange(MetadataSync.METADATA_AUTHORITY_URI, null, syncToMetadataNetwork);}
这个方法定义在文件packages/providers/ContactsProvider/src/com/android/providers/contacts/ContactsProvider2.java中。
上面的代码,获取到ContentResolver()对象,和query()类似,然后调用notifyChange()通知ContentResolver数据发生了变化,如下:
public void notifyChange(@NonNull Uri uri, ContentObserver observer, boolean syncToNetwork, @UserIdInt int userHandle) { try { getContentService().notifyChange( uri, observer == null ? null : observer.getContentObserver(), observer != null && observer.deliverSelfNotifications(), syncToNetwork ? NOTIFY_SYNC_TO_NETWORK : 0, userHandle); } catch (RemoteException e) { }}
这个方法定义在文件frameworks/base/core/java/android/content/ContentResolver.java中。
上面的代码调用getContentService()方法,从上文可知,getContentService()获取到的是ContentService的远程调用,因此getContentService().notifyChange()实质会运行到ContentService的notifyChange()方法,如下:
public void notifyChange(Uri uri, ......) { ...... try { ArrayList calls = new ArrayList(); synchronized (mRootNode) { mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications, flags, userHandle, calls); } final int numCalls = calls.size(); for (int i=0; itry { oc.mObserver.onChange(oc.mSelfChange, uri, userHandle); } catch (RemoteException ex) { ...... } } ...... } } finally { restoreCallingIdentity(identityToken); }}
这个方法定义在文件frameworks/base/services/core/java/com/android/server/content/ContentService.java中。
上面的代码中的mRootNode变量,在注册观察者的章节中,mRootNode封装了所有的观察者。调用collectObserversLocked()根据观察者监听的Uri类型把观察者封装到ArrayList的实例calls中,然后调用oc.mObserver.onChange()方法通知APP数据发生变化。
总结
本文详细阐述了ContentProvider的原理,从ContentProvider的query过程入手,全面详细分析了从query()的发起APP到ActivityManagerService,再到ContentProvider提供程序的整个流程和交互过程。以及分析了ContentService在ContentProvider的数据变化监测通知的架构中,扮演了观察者模式中的抽象主题,具体主题部分。
更多相关文章
- 浅谈Java中Collections.sort对List排序的两种方法
- Python list sort方法的具体使用
- python list.sort()根据多个关键字排序的方法实现
- Android(安卓)WebView 开发详解(一)
- Android中widget组件的开发流程
- android 进程优先级
- android的adb详解(多设备时adb调用)
- Android手动显示和隐藏软键盘方法总结
- Testing和Instrumentation