ContentService源码分析

来源:互联网 发布:手机桌面图标软件 编辑:程序博客网 时间:2024/06/08 18:39

简单介绍

ContentProvider按照一定规则暴露自己的接口给其它应用来访问自己应用的数据(其实就是自定义增删改查接口并暴露出去,让别的应用访问自己的数据)。当其他应用需要用到该应用的数据时,可以使用ContentResolver,而通过ContentResolver我们可以完成两大功能:
1 通过其对ContentProvider中的数据进行添加、删除、修改和查询操作
2 通过其来监听ContentProvider中数据的变化

那ContentResolver是如何实现这些功能的呢?其实,它内部主要就是调用了ContentService的相应方法,这就说明数据的更新等操作主要由ContentService来完成的。

接下来,我们就结合ContentResolver的使用来分析ContentService

从调用开始分析

在SystemServer的startOtherServices方法中,有这么一段代码

contentService = ContentService.main(context,mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL);............// 省略部分代码try {    if (contentService != null)        contentService.systemReady();} catch (Throwable e) {    reportWtf("making Content Service ready", e);}

在这里调用ContentService的main方法创建了一个ContentService实例,并调用了它的systemReady()方法。我们分开两步分析:
1. ContentService.main()分析

public static ContentService main(Context context, boolean factoryTest) {    ContentService service = new ContentService(context, factoryTest);    ServiceManager.addService(ContentResolver.CONTENT_SERVICE_NAME, service);    return service;}

这里主要就是创建了一个ContentService,并将其添加到ServiceManager中。我们进去看下它的构造函数

/*package*/ ContentService(Context context, boolean factoryTest) {    mContext = context;    mFactoryTest = factoryTest;}

这里只是简单的保存了两个变量的引用在本地
2. contentService.systemReady()

public void systemReady() {    getSyncManager();}private SyncManager getSyncManager() {    if (SystemProperties.getBoolean("config.disable_network", false)) {        return null;    }    synchronized(mSyncManagerLock) {        try {            // Try to create the SyncManager, return null if it fails (e.g. the disk is full).            if (mSyncManager == null) mSyncManager = new SyncManager(mContext, mFactoryTest);        } catch (SQLiteException e) {            Log.e(TAG, "Can't create SyncManager", e);        }        return mSyncManager;    }}

假如网络被禁止,则不获取SyncManager服务。SyncManager是数据同步的主要类

ContentService的registerContentObserver()方法分析

我们从ContentResolver入手:

/** * Register an observer class that gets callbacks when data identified by a * given content URI changes. * * @param uri The URI to watch for changes. This can be a specific row URI, or a base URI * for a whole class of content. * @param notifyForDescendents If <code>true</code> changes to URIs beginning with <code>uri</code> * will also cause notifications to be sent. If <code>false</code> only changes to the exact URI * specified by <em>uri</em> will cause notifications to be sent. If <code>true</code>, any URI values * at or below the specified URI will also trigger a match. * @param observer The object that receives callbacks when changes occur. * @see #unregisterContentObserver */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 {        getContentService().registerContentObserver(uri, notifyForDescendents,                observer.getContentObserver(), userHandle);    } catch (RemoteException e) {    }}

从上边的函数可以看到,ContentResolver的registerContentObserver()方法内部其实是调用了ContentService的registerContentObserver方法,我们进入查看

public void registerContentObserver(Uri uri, boolean notifyForDescendants,            IContentObserver observer) {    registerContentObserver(uri, notifyForDescendants, observer,            UserHandle.getCallingUserId());}/** * Register a content observer tied to a specific user's view of the provider. * @param userHandle the user whose view of the provider is to be observed.  May be *     the calling user without requiring any permission, otherwise the caller needs to *     hold the INTERACT_ACROSS_USERS_FULL permission.  Pseudousers USER_ALL and *     USER_CURRENT are properly handled; all other pseudousers are forbidden. */@Overridepublic 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的registerContentObserver方法内部实现很简单:就是将uri和observer的对应关系保存到mRootNode变量中

ContentService的nitofyChange()分析

我们从ContentResolver入手:

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) {    }}

从上边的函数可以看到,ContentResolver的notifyChange()方法内部其实是调用了ContentService的notifyChange方法,我们进入查看

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);}

上边主要有两大操作:
- 从mRootNode中获取所有匹配的ContentObserver并保存在变量calls中,遍历calls,调用每个ContentObserver的onChange()方法。假如出现异常:”Found dead observer, removing”
- 假如syncToNetwork为true,则调用syncManager.scheduleLocalSync()进行同步

0 0
原创粉丝点击