一、前言
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