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的代码,我们把这段代码贴出来:
接着分析IContentProvider provider = acquireProvider(url);这句话,在ContentResolver中acquireProvider(url)最终会走到
这个抽象函数中,而我们之前分析复过,其实我们获取的ContentResolver实例是ApplicationContentResolver,所以就会走到ContextIml中的mContentResolver.acquireProvider(Context context,String name)而这个里面是什么
返回的是mMainThread.acquireProvider(context, name);而mMainThread个又是什么呢?这个我们之前说过,他就是ActivityThread的实例,所以我们进ActivityThread去瞅瞅acquireProvider做了什么事情
首先去获取一下,看看是不是这个IContentProvider已经存在,存在就直接返回,不存在,就去创造一个,也就是
这几句话,首先创建了一个IActivityManager.ContentProviderHolder,这个是怎么创建的?他是个什么东西?我们先看看ActivityManagerNative.getDefault()是怎么返回IActivityManager的
而gDefault又是什么呢?
Singleton这个是什么呢?
这是一个抽象模板类,所以我们带进去就是这么一个类
所以上面gDefault.get()就变成了IActivityManager am = asInterface((IBinder)ServiceManager.getService("activity"));这句话,所以我们再进asInterface去看看
一目了然,最终返回一个ActivityManagerProxy这实例,而ActivityManagerProxy实例是什么呢?他继承于IActivityManager,所以最终我们的IActivityManager.ContentProviderHolder也就是ActivityManagerProxy.ContentProviderHolder,我们接着看ActivityManagerProxy.ContentProviderHolder的代码
接下来就是Binder的知识了,我们暂时不做研究,直接找到我们关心的也就是ContentProviderHolder.CREATOR.createFromParcel(reply);这句话,我们看看到底是ContentProviderHolder是个什么东西,我们找到ContentProviderHolder类是在IActivityManager中,ContentProviderHolder是个内部类
从代码可以看出ContentProviderHolder.CREATOR.createFromParcel(reply)最终是这样
给三个对象赋值,其他两个暂时不说,我们只看看provider是个什么东西,是怎么创建的?我们在provider定义的地方可以看出他是一个IContentProvider,然后我们去看看ContentProviderNative.asInterface
很明显了最终一个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);
这又是底层Binder的事情了,我们暂时不关心这个,我们直接找到mRemote.transact(IContentProvider.INSERT_TRANSACTION, data, reply, 0);这句话到了哪里,最终他会到ContentProviderNative类的
这个方法中,我们找到这部分代码
就是这几句话了,最关键的是insert(url, values);而insert也就是我们ContentProvider中insert中的。所以最终this.getContext().getContentResolver().insert(Uri url, ContentValues values)句话执行的就是我们ContentProvider中insert。这样我们就明白了其实ContentResolver中对数据库的操作最终都转化成了ContentProvider对数据库的操作。
而当我们继承ContentProvider的时候,insert走的就是我们继承里面的insert了,由于每个人写的代码不同,所以我们这里只引用关键的几句话
我们先看第一句话,这里有两个关键类,一个是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为例
首先就去new了一个DatabaseHelper,我们说过了DatabaseHelper是SQLiteOpenHelper的子类,这个构造函数我们不用去看,基本上都是一些赋值过程,把需要的值传进去,就这么简单,但是我们需要提一点就是,这里传进去了我们数据库的名字和version。然后接着看,对我们无关的我们跳过,直接找我们关心的,就是SQLiteDatabase db = mOpenHelper.getWritableDatabase();了,这个我们需要进入DatabaseHelper父类也就是SQLiteOpenHelper中观看了,进去之后就可以发现这个函数内容很多,当然了,我们还是只关心对我们有用的
首先去创建了一个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是暴露给我们操作数据库的接口,现在明白是怎么一回事了吧。
还是那句话,给大师饭后取乐,给后来者抛砖引玉,不要在背后骂我就行。
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是暴露给我们操作数据库的接口,现在明白是怎么一回事了吧。
还是那句话,给大师饭后取乐,给后来者抛砖引玉,不要在背后骂我就行。