浅析Android四大组件之一:ContentProvider 内容提供者 源码

本文探讨了Android中ContentProvider的工作原理,通过追踪源代码解析了如何通过getContentResolver()获取ContentResolver对象,并进一步调用insert方法。虽然没有深入系统层,但介绍了ContentProvider的基本使用和关键步骤。

今天在写代码的时候,发现我们用下面的这行代码就能够调用ContentProvider下面的insert方法,

Uri uri=getContentResolver().insert(MyContentProvider.uri,contentValues);

非常不理解,于是就去看源代码,也算是大概了解了工作原理。没有追到系统层,只是在应用层,所以只是简单的介绍,想要非常详细的解析,可以建议看下这篇博客,写的非常的好下面给处传送门:

http://blog.youkuaiyun.com/u010961631/article/details/14227421

由于我现在也是刚开始接触源代码,对系统层不是很了解,而且ContentProvider涉及到系统层的非常多,所以也不打算目前做了解。只是简单的做个介绍:

这里对于ContentProvider的基本用法不做介绍,不懂得话可以看下我的另外一篇博客:

http://blog.youkuaiyun.com/simon_crystin/article/details/68517050

下面就开始我是怎么追踪源代码的:

首先我们看 这个方法:

getContentResolver().insert(MyContentProvider.uri,contentValues);

我们先看看getContentResolver()这个方法:

public ContentResolver getContentResolver() {
        return mBase.getContentResolver();
    }

继续往下面看 getContentResolver();


public abstract class Context
public abstract ContentResolver getContentResolver();

这里定义了一个抽象方法,是Context下面的抽象方法。
肯定有个子类重写了这个方法,我们发现:class ContextImpl extends Context,
于是我们去搜索:

  @Override
    public ContentResolver getContentResolver() {
        return mContentResolver;
    }

果然在下面找到了这个方法。接着往下面看:

private final ApplicationContentResolver mContentResolver;

这里返回的是ApplicationContentResolver 的对象。

private static final class ApplicationContentResolver extends ContentResolver 

ApplicationContentResolver 继承自ContentResolver;
这就到了我们熟悉的地方了。终于是获得了ContentResolver 的对象。

我们去这下面找insert方法:

  public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url,
                @Nullable ContentValues values) {
        Preconditions.checkNotNull(url, "url");
        IContentProvider provider = acquireProvider(url);
        if (provider == null) {
            throw new IllegalArgumentException("Unknown URL " + url);
        }
        try {
            long startTime = SystemClock.uptimeMillis();
            Uri createdRow = provider.insert(mPackageName, url, values);
            long durationMillis = SystemClock.uptimeMillis() - startTime;
            maybeLogUpdateToEventLog(durationMillis, url, "insert", null /* where */);
            return createdRow;
        } catch (RemoteException e) {
            // Arbitrary and not worth documenting, as Activity
            // Manager will kill this process shortly anyway.
            return null;
        } finally {
            releaseProvider(provider);
        }
    }

这个方法做了什么操作呢?
IContentProvider provider = acquireProvider(url);
我们可以看到这个代码,我之前的理解是,通过Uri来获取ContentProvider对象(通过Uri来区分不同的对象,这个是比较基础的),如果这样想的话,那就有点低估Google工程师了。

这里我们再跟下去,看看acquireProvider()这个方法到底是怎么样呢?

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

这个时候,可以看到,这是一个抽象方法,那肯定在子类重写了。。

在前面的提到ApplicationContentResolver这个类中,我们找到了这个重写的方法:

 protected IContentProvider acquireProvider(Context context, String auth) {
            return mMainThread.acquireProvider(context,
                    ContentProvider.getAuthorityWithoutUserId(auth),
                    resolveUserIdFromAuthority(auth), true);
        }

这里我们可以看到,返回了一个ContentProvider。当然,还可以继续追下去,不过博主技能有限,并且对系统层不了解。就不再进行了解了。不过目前正在学系统层这一块。

整个流程:

  1、当我们调用getContentResolver().insert()后,将会通过getContentResolver()得到ContentResolver对象,然后调用该对象的insert()方法。
   2、在ContentResolver中,会通过acquireProvider()的方法得到IContentProvider对象,而这个对象的获取首先需要ActivityThread中向ActivityManagerService申请的ContentProvider的详细信息(ContentProviderHolder),然后利用这个Holder去得到(getIContentProvider)ContentProvider的远程代理对象(Transport对象)。
   3、拿到这个对象之后,调用其insert方法,该方法将会由ContentProvider传递给其子类(AbstractContactsProvider),并在子类中将insert操作转换为事务处理的方式(InsertInTransaction),AbstractContactsProvider中虽然将处理方式转换成事务的方式,但是却没有具体的实现,而是把具体的操作留给其子类(ContactsProvider2)完成。
   4、ContactsProvider2在实现过程中将会用相应的SQLiteOpenHelper去把操作转换成具体的SQLite语句并执行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AnjoyZhang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值