contentResolver与ContentProvider理解

来源:互联网 发布:架子鼓谱软件 编辑:程序博客网 时间:2024/05/12 04:33

注:

Application是一个完整的应用,比如某个apk,它对应一个Application,它里面可能包含n个Activity。

涉及到的类froyo/frameworks/base/core/java/android/app/ApplicationContext.java

          froyo/frameworks/base/core/java/android/app/ActivityThread.java

          froyo/frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

 

当我们启动手机之后,如果需要启动一个activity,ActivityThread,ActivityManagerService就开始发挥作用了,这里不做细述。

当我们真正的启动一个activity的时候,我们会把当前Application的ApplicationContext传进去,

ApplicationContext实例持有一个mContextResolver对象,该对象对应于ApplicationContext的

内部类ApplicationContentResolver.

当activity调用getContentResolver()时,我们实际调用的是当前ApplicationContext中的mContextResolver.

 

由于黑色的继承关系,我们可以得到红色的调用关系

代码片段如下:

Activity调用ContextWrapper的方法

     getContentResolver() {

        mBase.getContentResolver();

     }

然后会调用到ApplicationContext的方法

     getContentResolver() {

       return mContentResolver;

     }

其中:

mContentResolve r = new ApplicationContentResolver(this, mainThread);

 

    private static final class ApplicationContentResolver extends ContentResolver {
        public ApplicationContentResolver(Context context,
                                          ActivityThread mainThread)
        {
            super(context);
            mMainThread = mainThread;
        }

        @Override
        protected IContentProvider acquireProvider(Context context, String name)
        {
            return mMainThread.acquireProvider (context, name);
        }

        @Override
        public boolean releaseProvider(IContentProvider provider)
        {
            return mMainThread.releaseProvider(provider);
        }
        
        private final ActivityThread mMainThread;
    }

 

 

当执行mContentResolver.query()的时候,我们会调用父类ContentResolver的query();

public final Cursor query(Uri uri, String[] projection,
            String selection, String[] selectionArgs, String sortOrder) {
        IContentProvider provider = acquireProvider(uri); 
        if (provider == null) {
            return null;
        }
        try {
            Cursor qCursor = provider.query(uri, projection, selection, selectionArgs, sortOrder);
            if(qCursor == null) {
                releaseProvider(provider);
                return null;
            }
            //Wrap the cursor object into CursorWrapperInner object
            return new CursorWrapperInner(qCursor, provider);
        } catch (RemoteException e) {
            releaseProvider(provider);
            return null;
        } catch(RuntimeException e) {
            releaseProvider(provider);
            throw e;
        }
    }

 

 public final IContentProvider acquireProvider(Uri uri)
    {
        if (!SCHEME_CONTENT.equals(uri.getScheme())) {
            return null;
        }
        String auth = uri.getAuthority();
        if (auth != null) {
            return acquireProvider(mContext, uri.getAuthority()); 
        }
        return null;
    }

 

此时,会调用子类实例aquireProvider(Context,name);

mMainThread.acquireProvider (context, name);

实现为:

public final IContentProvider acquireProvider (Context c, String name) {
        IContentProvider provider = getProvider (c, name);
        if(provider == null)
            return null;
        IBinder jBinder = provider.asBinder();  //获得binder对象,跨进程传递数据。 
        synchronized(mProviderMap) {
            ProviderRefCount prc = mProviderRefCountMap.get(jBinder); 
            if(prc == null) {
                mProviderRefCountMap.put(jBinder, new ProviderRefCount(1)); 
            } else {
                prc.count++;
            } //end else
        } //end synchronized
        return provider;
    }

 

private final IContentProvider getProvider (Context context, String name) {
        synchronized(mProviderMap) {
            final ProviderRecord pr = mProviderMap .get(name); //ActivityThread中持有所有的Provider的实例 
            if (pr != null) {
                return pr.mProvider;
            }
        }
        //如果确实没有,则查找,并install,再没有就直接抛异常了。 
        IActivityManager.ContentProviderHolder holder = null;
        try {
            holder = ActivityManagerNative.getDefault().getContentProvider(
                getApplicationThread(), name);
        } catch (RemoteException ex) {
        }
        if (holder == null) {
            Log.e(TAG, "Failed to find provider info for " + name);
            return null;
        }
        if (holder.permissionFailure != null) {
            throw new SecurityException("Permission " + holder.permissionFailure
                    + " required for provider " + name);
        }

        IContentProvider prov = installProvider(context, holder.provider,
                holder.info, true);
        //Log.i(TAG, "noReleaseNeeded=" + holder.noReleaseNeeded);
        if (holder.noReleaseNeeded || holder.provider == null) {
            // We are not going to release the provider if it is an external
            // provider that doesn't care about being released, or if it is
            // a local provider running in this process.
            //Log.i(TAG, "*** NO RELEASE NEEDED");
            synchronized(mProviderMap) {
                mProviderRefCountMap.put(prov.asBinder(), new ProviderRefCount(10000));
            }
        }
        return prov;
    }

 

到这里的话,ContentResovler与ContentProvider的关系就搞懂了,具体其他的细节,将分为不同的方面,分别讲述。


以下加入自己的理解:

首先在androidManinfest.xml注册provider,这样做是为了让系统底层调用继承contentprovider的子类。甚至contentprovider的onCreate方法也是系统底层调用的。这个方法可以调用SQLiteOpenHelper来创建数据库。

第二当在其他类中调用ContentResovler的时候,实际上间接是调用ContentProvider相应的方法。方法内在调用SQLiteOpenHelper来实现操作。但是中间加上ContentProvider这个作为隔离,导致一边修改数据库,同时读取数据库的时候可以达到线程安全。因为ContentProvider加了异步。具体看上面分析synchronized。

第三用到ContentProvider会设计多个操作类。

类层级关系:ContentResovler方法内调用ContentProvider-》SQLiteOpenHelper-》SQLiteDatabase

ContentProvider这个层次就用到URI层次匹配了对数据库进行增删改查。而不用sql语句。会用到UriMatcher和Cursor类。

0 0