ContentProvider源码分析(原)

一、前言


        ContentProvider作为Android四大组件之一,承担着数据存储的作用,本文用一个最典型的删除(delete)操作,按照Android源码, 从应用层的getContentResolver()入手,一步步的分析到ContentProvider内部,最终到达SQLite的操作
    getContentResolver().delete();
        这个简单的操作其实包含了两个步骤:
        1、通过getContentResolver()得到需要的ContentProvider对象;
        2、通过delete()操作,将ContentProvider中的数据删除;

        下面我们就开启此次漫长的旅程。


二、getContentResolver

        看标题,我们是要得到一个ContentResolver的对象,这就产生了两个疑问:
        1、ContentResolver对象与ContentProvider有什么关系?
        2、我们是如何得到ContentProvider中的内容呢?

        为了解答这两个问题,我们需要从代码的最源头开始分析:


2.1、ContentResolver与ContentProvider的关系

        先来看看得到ContentResolver的过程:
    @ContextImpl.java
    public ContentResolver getContentResolver() {
        return mContentResolver;
    }
        这里的mContentResolver是在ContextImpl的init中完成初始化的:
    final void init(Resources resources, ActivityThread mainThread, UserHandle user) {
        mPackageInfo = null;
        mBasePackageName = null;
        mResources = resources;
        mMainThread = mainThread;
        //mContentResolver被初始化为ApplicationContentResolver对象
        mContentResolver = new ApplicationContentResolver(this, mainThread, user);
        mUser = user;
    }
        mContentResolver被初始化为ApplicationContentResolver对象,我们再来看ApplicationContentResolver这个类,他是ContextImpl的内部类:
    private static final class ApplicationContentResolver extends ContentResolver {
        public ApplicationContentResolver( Context context, ActivityThread mainThread, UserHandle user) { }
        protected IContentProvider acquireProvider(Context context, String auth) { }
        protected IContentProvider acquireExistingProvider(Context context, String auth) { }
        public boolean releaseProvider(IContentProvider provider) { }
        protected IContentProvider acquireUnstableProvider(Context c, String auth) { }
        public boolean releaseUnstableProvider(IContentProvider icp) { }
        public void unstableProviderDied(IContentProvider icp) { }
    }
        他提供了得到IContentProvider的各种方法,而且继承自ContentResolver类,我们来看这个类的属性:
    @ContentResolver.java
    public abstract class ContentResolver { }
        可以看到,ContentResolver并没有继承任何的类或者接口,因此,我们可以认为, 从继承关系上来讲,ContentResolver与ContentProvider没有任何关系

        那么我们是如何最终得到ContentProvider的呢?


2.2、如何通过ContentResolver得到ContentProvider

        下面我们来解答第二个疑问,我们是 如何通过ContentResolver去查询到ContentProvider中的内容呢?
        虽然我们知道这两者从继承关系上并没有什么联系,但是ContentResolver的内部却出现了我们熟悉的一些方法,包括:  
    public final Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {}
    public final int delete(Uri url, String where, String[] selectionArgs){}
    public final int update(Uri uri, ContentValues values, String where, String[] selectionArgs) {}
    public final Uri insert(Uri url, ContentValues values){}
        这就说明,两者在功能上一定有联系,下面我们从最开始的delete操作去分析,看两者究竟有什么关系。
        回到最初的调用地点,当我们需要通过ContentProvider去delete一项数据时,就会调用getContentResolver().delete()方法,上面分析道, getContentResolver()得到的就是ApplicationContentResolver的对象,而ApplicationContentResolver又继承自ContentResolver。因此,delete的操作就落在ContentResolver中:
    @ContentResolver.java
    public final int delete(Uri url, String where, String[] selectionArgs)
    {
        IContentProvider provider = acquireProvider(url);
        try {
            int rowsDeleted = provider.delete(url, where, selectionArgs);
        } catch (RemoteException e) {
        } finally {
        }
    }
        在这一步中,我们先通过acquireProvider()得到IContentProvider对象,然后调用IContentProvider对象的delete方法进行操作。那么,这里是如何通过acquireProvider()得到IContentProvider对象的呢?
    public final IContentProvider acquireProvider(Uri uri) {
        //安全确认
        if (!SCHEME_CONTENT.equals(uri.getScheme())) {
            return null;
        }
        final String auth = uri.getAuthority();
        if (auth != null) {
            //继续调用
            return acquireProvider(mContext, auth);
        }
        return null;
    }
        继续看:
    protected abstract IContentProvider acquireProvider(Context c, String name);
        这里竟然遇到了抽象的acquireProvider,说明这个方法需要到子类中实现,那么我们就去ApplicationContentResolver中去看看:
    @ContextImpl.java
    private static final class ApplicationContentResolver extends ContentResolver {
        //果然找到了acquireProvider方法
        protected IContentProvider acquireProvider(Context context, String auth) {
            return mMainThread.acquireProvider(context, auth, mUser.getIdentifier(), true);
        }
    }
        我们确实在ApplicationContentResolver中找到了acquireProvider()方法,而且发现 acquireProvider方法所提供的返回值是来自于mMainThread对象的acquireProvider方法
        那么,这个mMainThread是哪里来的呢?

        接下来所介绍的流程,比较复杂,各位看好了。


2.3、寻找mMainThread对象来历

        在ActivityThread中创建一个Activity之后,就会调用ActivityThread中的createBaseContextForActivity()方法,为当前的Activity创建Context对象和mMainThread对象:
    @ActivityThread.java
    private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) {
        //这里就是要创建Context对象的地方
        ContextImpl appContext = new ContextImpl();
        //并把当前ActivityThread对象传递给ContextImpl的init方法中
        appContext.init(r.packageInfo, r.token, this);
    }
        此时将会调用ContextImpl中的init方法:
    @ContextImpl.java
    //这里的mainThread就是ActivityThread对象
    final void init(LoadedApk packageInfo, IBinder activityToken, ActivityThread mainThread) {
        init(packageInfo, activityToken, mainThread, null, null, Process.myUserHandle());
    }
    final void init(LoadedApk packageInfo, IBinder activityToken, ActivityThread mainThread, Resources container, String basePackageName, UserHandle user){
        //mMainThread就是ActivityThread对象
        mMainThread = mainThread;
        mContentResolver = new ApplicationContentResolver(this, mainThread, user);
    }
        这个过程我们发现, mMainThread就是ActivityThread对象,因此在2.2中我们介绍的mMainThread.acquireProvider()相当于:
    ActivityThread.acquireProvider();
        我们继续看:
    @ActivityThread.java
    public final IContentProvider acquireProvider( Context c, String auth, int userId, boolean stable) {
        final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
        if (provider != null) {
            return provider;
        }

        IActivityManager.ContentProviderHolder holder = null;
        try {
            holder = ActivityManagerNative.getDefault().getContentProvider( getApplicationThread(), auth, userId, stable);
        } catch (RemoteException ex) {
        }

        holder = installProvider(c, holder, holder.info, true , holder.noReleaseNeeded, stable);
        return holder.provider;
    }
        这里可以看到, ActivityThread中存在一个HashMap用来缓存所有的provider。每一次对provider的请求,都会先通过acquireExistingProvider()查询是否已经被缓存,如果没有缓存,就去创建该provider的ContentProviderHolder对象,同时缓存下来方便下次调用

        我们假设当前没有ContactsProvider的缓存,那么将会通过ActivityManagerNative.getDefault().getContentProvider()创建该provider,下面我们来分析这个创建的过程。


2.4、ActivityThread创建ContentProvider的过程。

        前面说过,ActivityThread创建ContentProvider是通过以下方式实现的:
        ActivityManagerNative.getDefault().getContentProvider( getApplicationThread(), auth, userId, stable);

        这个过程可以分为两步:

        1、我们来看通过ActivityManagerNative.getDefault()所得到的对象;

        2、我们再来分析这个对象的getContentProvider方法

2.4.1、ActivityManagerNative对象。

        我们先介绍一下ActivityManagerService服务。
        当系统启动后,在SystemServer中就会将一些重要的Server启动起来,其中就包括ActivityManagerService:
    @SystemServer.java
    public void run() {
        //启动ActivityManagerService
        context = ActivityManagerService.main(factoryTest);
        //注册ActivityManagerService
        ActivityManagerService.setSystemProcess();
    }
        上面调用ActivityManagerService.main方法的结果就是启动ActivityManagerService,然后调用setSystemProcess把ActivityManagerService注册给系统:
    @ActivityManagerService.java
    public static void setSystemProcess() {
        try {
            ActivityManagerService m = mSelf;
            //将自己注册为“activity”的Server            
            ServiceManager.addService("activity", m, true);
            ServiceManager.addService("meminfo", new MemBinder(m));
            ServiceManager.addService("gfxinfo", new GraphicsBinder(m));
            ServiceManager.addService("dbinfo
  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值