ContentProvider 那点事儿

    ContentProvider Content内容,Provider提供者,所以就是内容提供者。
    ContentResolver Content内容,Resolver解析者,所以就是内容解析者。
    这两个是什么关系呢?我们通过插入一条数据过程来分析其关系:
    首先通过this.getContext()获取到Context,而Context中getContentResolver()是个抽象函数,在ContextWrapper中实现,而ContextWrapper中的成员变量mBase是一个ContextIml实例,所以this.getContext().getContentResolver()这句话最终就是ContextIml.getContentResolver()也就是ApplicationContentResolver的一个实例。ApplicationContentResolver继承与ContentResolver。所以this.getContext().getContentResolver().insert(Uri url, ContentValues values)也就ContentResolver中insert的代码,我们把这段代码贴出来:
    public final Uri insert(Uri url, ContentValues values)
    {
        IContentProvider provider = acquireProvider(url);
        if (provider == null) {
            throw new IllegalArgumentException("Unknown URL " + url);
        }
        try {
            long startTime = SystemClock.uptimeMillis();
            Uri createdRow = provider.insert(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);这句话,在ContentResolver中acquireProvider(url)最终会走到
protected abstract IContentProvider acquireProvider(Context c, String name);

这个抽象函数中,而我们之前分析复过,其实我们获取的ContentResolver实例是ApplicationContentResolver,所以就会走到ContextIml中的mContentResolver.acquireProvider(Context context,String name)而这个里面是什么
        @Override
        protected IContentProvider acquireProvider(Context context, String name) {
            return mMainThread.acquireProvider(context, name);
        }

返回的是mMainThread.acquireProvider(context, name);而mMainThread个又是什么呢?这个我们之前说过,他就是ActivityThread的实例,所以我们进ActivityThread去瞅瞅acquireProvider做了什么事情
    public final IContentProvider acquireProvider(Context c, String name) {
        IContentProvider provider = acquireExistingProvider(c, name);
        if (provider != null) {
            return provider;
        }

        // There is a possible race here.  Another thread may try to acquire
        // the same provider at the same time.  When this happens, we want to ensure
        // that the first one wins.
        // Note that we cannot hold the lock while acquiring and installing the
        // provider since it might take a long time to run and it could also potentially
        // be re-entrant in the case where the provider is in the same process.
        IActivityManager.ContentProviderHolder holder = null;
        try {
            holder = ActivityManagerNative.getDefault().getContentProvider(
                    getApplicationThread(), name);
        } catch (RemoteException ex) {
        }
        if (holder == null) {
            Slog.e(TAG, "Failed to find provider info for " + name);
            return null;
        }

        // Install provider will increment the reference count for us, and break
        // any ties in the race.
        provider = installProvider(c, holder.provider, holder.info,
                true /*noisy*/, holder.noReleaseNeeded);
        if (holder.provider != null && provider != holder.provider) {
            if (localLOGV) {
                Slog.v(TAG, "acquireProvider: lost the race, releasing extraneous "
                        + "reference to the content provider");
            }
            try {
                ActivityManagerNative.getDefault().removeContentProvider(
                        getApplicationThread(), name);
            } catch (RemoteException ex) {
            }
        }
        return provider;
    }

首先去获取一下,看看是不是这个IContentProvider已经存在,存在就直接返回,不存在,就去创造一个,也就是
        IActivityManager.ContentProviderHolder holder = null;
        try {
            holder = ActivityManagerNative.getDefault().getContentProvider(
                    getApplicationThread(), name);
        } catch (RemoteException ex) {
        }
        if (holder == null) {
            Slog.e(TAG, "Failed to find provider info for " + name);
            return null;
        }

        // Install provider will increment the reference count for us, and break
        // any ties in the race.
        provider = installProvider(c, holder.provider, holder.info,
                true /*noisy*/, holder.noReleaseNeeded);
        if (holder.provider != null && provider != holder.provider) {
            if (localLOGV) {
                Slog.v(TAG, "acquireProvider: lost the race, releasing extraneous "
                        + "reference to the content provider");
            }
            try {
                ActivityManagerNative.getDefault().removeContentProvider(
                        getApplicationThread(), name);
            } catch (RemoteException ex) {
            }
        }

这几句话,首先创建了一个IActivityManager.ContentProviderHolder,这个是怎么创建的?他是个什么东西?我们先看看ActivityManagerNative.getDefault()是怎么返回IActivityManager的
    static public IActivityManager getDefault() {
        return gDefault.get();
    }

而gDefault又是什么呢?
    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

Singleton这个是什么呢?
public abstract class Singleton<T> {
    private T mInstance;

    protected abstract T create();

    public final T get() {
        synchronized (this) {
            if (mInstance == null) {
                mInstance = create();
            }
            return mInstance;
        }
    }
}

这是一个抽象模板类,所以我们带进去就是这么一个类
public abstract class Singleton<IActivityManager> {
    private IActivityManager mInstance;

    protected abstract IActivityManager create();

    public final IActivityManager get() {
        synchronized (this) {
            if (mInstance == null) {
                mInstance = create();
            }
            return mInstance;
        }
    }
}

所以上面gDefault.get()就变成了IActivityManager am = asInterface((IBinder)ServiceManager.getService("activity"));这句话,所以我们再进asInterface去看看
    static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        return new ActivityManagerProxy(obj);
    }

一目了然,最终返回一个ActivityManagerProxy这实例,而ActivityManagerProxy实例是什么呢?他继承于IActivityManager,所以最终我们的IActivityManager.ContentProviderHolder也就是ActivityManagerProxy.ContentProviderHolder,我们接着看ActivityManagerProxy.ContentProviderHolder的代码
    public ContentProviderHolder getContentProvider(IApplicationThread caller,
                                                    String name) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeString(name);
        mRemote.transact(GET_CONTENT_PROVIDER_TRANSACTION, data, reply, 0);
        reply.readException();
        int res = reply.readInt();
        ContentProviderHolder cph = null;
        if (res != 0) {
            cph = ContentProviderHolder.CREATOR.createFromParcel(reply);
        }
        data.recycle();
        reply.recycle();
        return cph;
    }

接下来就是Binder的知识了,我们暂时不做研究,直接找到我们关心的也就是ContentProviderHolder.CREATOR.createFromParcel(reply);这句话,我们看看到底是ContentProviderHolder是个什么东西,我们找到ContentProviderHolder类是在IActivityManager中,ContentProviderHolder是个内部类
    public static class ContentProviderHolder implements Parcelable {
        public final ProviderInfo info;
        public IContentProvider provider;
        public boolean noReleaseNeeded;

        public ContentProviderHolder(ProviderInfo _info) {
            info = _info;
        }

        public int describeContents() {
            return 0;
        }

        public void writeToParcel(Parcel dest, int flags) {
            info.writeToParcel(dest, 0);
            if (provider != null) {
                dest.writeStrongBinder(provider.asBinder());
            } else {
                dest.writeStrongBinder(null);
            }
            dest.writeInt(noReleaseNeeded ? 1:0);
        }

        public static final Parcelable.Creator<ContentProviderHolder> CREATOR
                = new Parcelable.Creator<ContentProviderHolder>() {
            public ContentProviderHolder createFromParcel(Parcel source) {
                return new ContentProviderHolder(source);
            }

            public ContentProviderHolder[] newArray(int size) {
                return new ContentProviderHolder[size];
            }
        };

        private ContentProviderHolder(Parcel source) {
            info = ProviderInfo.CREATOR.createFromParcel(source);
            provider = ContentProviderNative.asInterface(
                source.readStrongBinder());
            noReleaseNeeded = source.readInt() != 0;
        }
    };

从代码可以看出ContentProviderHolder.CREATOR.createFromParcel(reply)最终是这样
            info = ProviderInfo.CREATOR.createFromParcel(source);
            provider = ContentProviderNative.asInterface(
                source.readStrongBinder());
            noReleaseNeeded = source.readInt() != 0;

给三个对象赋值,其他两个暂时不说,我们只看看provider是个什么东西,是怎么创建的?我们在provider定义的地方可以看出他是一个IContentProvider,然后我们去看看ContentProviderNative.asInterface
    static public IContentProvider asInterface(IBinder obj)
    {
        if (obj == null) {
            return null;
        }
        IContentProvider in =
            (IContentProvider)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        return new ContentProviderProxy(obj);
    }

很明显了最终一个ContentProviderProxy,ContentProviderProxy implements IContentProviderEx 而 IContentProviderEx又继承于IContentProvider。
现在我们可以看清mMainThread.acquireProvider(context, name);的真面目了,也就是一个ContentProviderProxy的实例。也就是我们public final Uri insert(Uri url, ContentValues values)的时候IContentProvider provider = acquireProvider(url);获取到的provider其实是一个ContentProviderProxy的实例。所以我们回到最开始接着看,也就是Uri createdRow = provider.insert(url, values);这句话了,经过以上分析这句话也就是ContentProviderProxy.insert(url, values);
    public Uri insert(Uri url, ContentValues values) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        try {
            data.writeInterfaceToken(IContentProvider.descriptor);

            url.writeToParcel(data, 0);
            values.writeToParcel(data, 0);

            mRemote.transact(IContentProvider.INSERT_TRANSACTION, data, reply, 0);

            DatabaseUtils.readExceptionFromParcel(reply);
            Uri out = Uri.CREATOR.createFromParcel(reply);
            return out;
        } finally {
            data.recycle();
            reply.recycle();
        }
    }

这又是底层Binder的事情了,我们暂时不关心这个,我们直接找到mRemote.transact(IContentProvider.INSERT_TRANSACTION, data, reply, 0);这句话到了哪里,最终他会到ContentProviderNative类的
    @Override
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)

这个方法中,我们找到这部分代码
    case INSERT_TRANSACTION:
    {
        data.enforceInterface(IContentProvider.descriptor);
        Uri url = Uri.CREATOR.createFromParcel(data);
        ContentValues values = ContentValues.CREATOR.createFromParcel(data);

        Uri out = insert(url, values);
        reply.writeNoException();
        Uri.writeToParcel(reply, out);
        return true;
    }

就是这几句话了,最关键的是insert(url, values);而insert也就是我们ContentProvider中insert中的。所以最终this.getContext().getContentResolver().insert(Uri url, ContentValues values)句话执行的就是我们ContentProvider中insert。这样我们就明白了其实ContentResolver中对数据库的操作最终都转化成了ContentProvider对数据库的操作。

而当我们继承ContentProvider的时候,insert走的就是我们继承里面的insert了,由于每个人写的代码不同,所以我们这里只引用关键的几句话
    SQLiteDatabase db = mOpenHelper.getWritableDatabase();
    final long rowId = db.insert(args.table, null, initialValues);

    我们先看第一句话,这里有两个关键类,一个是SQLiteDatabase,一个是SQLiteOpenHelper。
    SQLiteDatabase SQLite支持SQ语言的精简版的,Database数据库,所以支持SQ语言的精简版的数据库。
    SQLiteOpenHelper SQLite 支持SQ语言的精简版的数据库,Open打开,Helper帮手,所以就是打开支持SQ语言的精简版的数据库的帮手。

    这样一说就很明显了,SQLiteOpenHelper大致功能就是帮助我们打开SQLiteDatabase数据库的。这我们从SQLiteDatabase db = mOpenHelper.getWritableDatabase();这句话也可以得到验证。为了能深入学习,我们以frameworks/base/packages/SettingsProvider包为例来学写,使用ContentProvider基本上就是一个定式了,这个SettingsProvider也不利外,都会用到三个关键类,第一个DatabaseHelper继承于SQLiteOpenHelper,第二个SettingsProvider继承于ContentProvider,第三个就是SQLiteDatabase,这个不需要重写。现在我们就分析一下这三者的关系,首先当我们启动一个含有ContentProvider的包是,就会先走到ContentProvider的onCreate()至于是为什么,这里先不讲,我们只看这个onCreate()做了什么,以SettingsProvider为例
    @Override
    public boolean onCreate() {
        mOpenHelper = new DatabaseHelper(getContext());
        mBackupManager = new BackupManager(getContext());

        if (!ensureAndroidIdIsSet()) {
            return false;
        }

        // Watch for external modifications to the database file,
        // keeping our cache in sync.
        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
        db.enableWriteAheadLogging();
        sObserverInstance = new SettingsFileObserver(db.getPath());
        sObserverInstance.startWatching();
        startAsyncCachePopulation();
        return true;
    }

首先就去new了一个DatabaseHelper,我们说过了DatabaseHelper是SQLiteOpenHelper的子类,这个构造函数我们不用去看,基本上都是一些赋值过程,把需要的值传进去,就这么简单,但是我们需要提一点就是,这里传进去了我们数据库的名字和version。然后接着看,对我们无关的我们跳过,直接找我们关心的,就是SQLiteDatabase db = mOpenHelper.getWritableDatabase();了,这个我们需要进入DatabaseHelper父类也就是SQLiteOpenHelper中观看了,进去之后就可以发现这个函数内容很多,当然了,我们还是只关心对我们有用的
        boolean success = false;
        SQLiteDatabase db = null;
        if (mDatabase != null) mDatabase.lock();
        try {
            mIsInitializing = true;
            if (mName == null) {
                db = SQLiteDatabase.create(null);
            } else {
                db = mContext.openOrCreateDatabase(mName, 0, mFactory, mErrorHandler);
            }

            int version = db.getVersion();
            if (version != mNewVersion) {
                db.beginTransaction();
                try {
                    if (version == 0) {
                        onCreate(db);
                    } else {
                        if (version > mNewVersion) {
                            onDowngrade(db, version, mNewVersion);
                        } else {
                            onUpgrade(db, version, mNewVersion);
                        }
                    }
                    db.setVersion(mNewVersion);
                    db.setTransactionSuccessful();
                } finally {
                    db.endTransaction();
                }
            }

            onOpen(db);
            success = true;
            return db;
        }

    首先去创建了一个SQLiteDatabase对象,这个mName是什么呢?就是我们构造函数是传进来的名字,在这里就是"settings.db",然后判断version,这个version也是我们前面提到构造函数传进来的version,当version为0时就走onCreate(db),我们找一下这个onCreate(db)是一个抽象函数,他的实现,是在继承了SQLiteOpenHelper的子类中,也就是我们上面提到的DatabaseHelper中,我们去看看,发现里面基本上都是一些sq语句,去创建数据Table。至于是怎么创建的我们现在不关心。当version不等于0是,还有一个判断,就是我们新的version小于老的version就报错,相反就去更新数据库onUpgrade,这个和onCreate一样,最终去了DatabaseHelper中,这里的代码就随意我们怎么写了,根据我们的需要,去更新不同的table了。

至此我们已经明白了SQLiteOpenHelper,ContentProvider,SQLiteDatabase三个的关系了,就是ContentProvider通过SQLiteOpenHelper得到SQLiteDatabase,然后对SQLiteDatabase中的数据进行修改操作。而ContentResolver通过一系列的转换最终转换成ContentProvider,而ContentResolver是暴露给我们操作数据库的接口,现在明白是怎么一回事了吧。

还是那句话,给大师饭后取乐,给后来者抛砖引玉,不要在背后骂我就行。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值