转自 http://blog.csdn.net/u010961631/
一、前言
- 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;
- }
- 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;
- }
- 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) { }
- }
- @ContentResolver.java
- public abstract class ContentResolver { }
那么我们是如何最终得到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){}
回到最初的调用地点,当我们需要通过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 {
- }
- }
- 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);
- @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);
- }
- }
那么,这个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.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);
- }
- 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;
- }
我们假设当前没有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.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", new DbBinder(m));
- } catch (PackageManager.NameNotFoundException e) {
- }
- }
- public final class ActivityManagerService
- extends ActivityManagerNative
- implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {}
这样我们就对ActivityManagerNative的结构有了大致的了解, 根据Binder通讯机制,如果我们跨进程去请求ActivityManagerService的服务时,就会调用他的asBinder()方法,并把他的IBinder对象返回给客户端使用 。
接着我们上面的分析,我们在2.4节中把创建ContentProvider分为两步, 第一步就是得到ActivityManagerNative.getDefault()对象 ,现在我们来看源码:
- @ActivityManagerNative.java
- static public IActivityManager getDefault() {
- return gDefault.get();
- }
- private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
- protected IActivityManager create() {
- IBinder b = ServiceManager.getService("activity");
- IActivityManager am = asInterface(b);
- return am;
- }
- };
1、通过getService("activity")得到ActivityManagerService的远程Binder;
2、利用得到的Biner对象通过asInterface()方法,得到这个服务的远程代理;
对于得到Binder对象,这是由Binder系统决定的,我们无需多看,我们来看一下如何通过Binder得到服务的远程代理:
- 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);
- }
- ActivityManagerNative.getDefault().
- getContentProvider( getApplicationThread(), auth, userId, stable);
- ActivityManagerProxy.getContentProvider(getApplicationThread(), auth, userId, stable);;
2.4.2、代理对象的getContentProvider操作
这一步当然是在ActivityManagerProxy类中发生的:- @ActivityManagerNative.java
- class ActivityManagerProxy implements IActivityManager{
- public ContentProviderHolder getContentProvider(IApplicationThread caller,
- String name, int userId, boolean stable) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(caller != null ? caller.asBinder() : null);
- data.writeString(name);
- data.writeInt(userId);
- data.writeInt(stable ? 1 : 0);
- //向ActivityManagerNative发送请求
- 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;
- }
- }
而ActivityManagerNative需要在onTransact()中去接收请求:
- @ActivityManagerNative.java
- public abstract class ActivityManagerNative extends Binder implements IActivityManager{
- //处理各种请求
- public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
- switch (code) {
- case GET_CONTENT_PROVIDER_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder b = data.readStrongBinder();
- IApplicationThread app = ApplicationThreadNative.asInterface(b);
- String name = data.readString();
- int userId = data.readInt();
- boolean stable = data.readInt() != 0;
- //调用ActivityManagerService的getContentProvider方法
- ContentProviderHolder cph = getContentProvider(app, name, userId, stable);
- reply.writeNoException();
- if (cph != null) {
- reply.writeInt(1);
- cph.writeToParcel(reply, 0);
- } else {
- reply.writeInt(0);
- }
- return true;
- }
- }
- }
- }
- @ActivityManagerService.java
- public final ContentProviderHolder getContentProvider( IApplicationThread caller, String name, int userId, boolean stable) {
- return getContentProviderImpl(caller, name, null, stable, userId);
- }
- private final ContentProviderHolder getContentProviderImpl(IApplicationThread caller, String name, IBinder token, boolean stable, int userId) {
- ContentProviderRecord cpr;
- ContentProviderConnection conn = null;
- ProviderInfo cpi = null;
- synchronized(this) {
- //查询缓存中是否已经存在该ContentProviderRecord
- cpr = mProviderMap.getProviderByName(name, userId);
- boolean providerRunning = cpr != null;
- if (providerRunning) {
- //如果该provider已经被运行过
- //得到该ContentProviderRecord的ProviderInfo
- cpi = cpr.info;
- if (r != null && cpr.canRunHere(r)) {
- //直接将ContentProviderHolder传给客户端即可
- ContentProviderHolder holder = cpr.newHolder(null);
- //清空其provider,由客户端自己去初始化provider的对象
- holder.provider = null;
- return holder;
- }
- }
- if (!providerRunning) {
- //当前没有运行
- //加载该provider的包,得到ProviderInfo
- cpi = AppGlobals.getPackageManager().resolveContentProvider(name, STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS, userId);
- //为当前provider创建ContentProviderRecord
- ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
- cpr = mProviderMap.getProviderByClass(comp, userId);
- //缓存当前的ContentProviderRecord
- mProviderMap.putProviderByName(name, cpr);
- conn = incProviderCountLocked(r, cpr, token, stable);
- }
- }
- //将ContentProviderHolder传给客户端
- return cpr != null ? cpr.newHolder(conn) : null;
- }
1、通过ContentProviderRecord.info可以得到当前provider的详细信息 ,包括该provider的authority、readPermission、writePermission、uriPermissionPatterns等重要信息;
2、可以通过ContentProviderRecord.newHolder()方法,生成一个针对当前provider的详细信息 ,我们需要把这些信息打包为Holder传递给ActivityThread使用。
我们再回到ActivityThread中的acquireProvider()里面:
- public final IContentProvider acquireProvider( Context c, String auth, int userId, boolean stable) {
- final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
- IActivityManager.ContentProviderHolder holder = null;
- try {
- //得到ContentProviderHolder对象
- holder = ActivityManagerNative.getDefault().getContentProvider( getApplicationThread(), auth, userId, stable);
- } catch (RemoteException ex) {
- }
- //用provider信息去初始化当前的provider
- holder = installProvider(c, holder, holder.info, true , holder.noReleaseNeeded, stable);
- //得到provider对象
- return holder.provider;
- }
- private IActivityManager.ContentProviderHolder installProvider(Context context, IActivityManager.ContentProviderHolder holder, ProviderInfo info, boolean noisy, boolean noReleaseNeeded, boolean stable) {
- ContentProvider localProvider = null;
- IContentProvider provider;
- if (holder == null || holder.provider == null) {
- //当前客户端没有得到过该provider,因此需要获得该provider远程代理
- Context c = null;
- ApplicationInfo ai = info.applicationInfo;
- if (context.getPackageName().equals(ai.packageName)) {
- //如果要获得的provider就在当前发出请求的客户端
- c = context;
- } else if (mInitialApplication != null && mInitialApplication.getPackageName().equals(ai.packageName)) {
- c = mInitialApplication;
- } else {
- try {
- //为要创建的provider创建Context对象
- c = context.createPackageContext(ai.packageName, Context.CONTEXT_INCLUDE_CODE);
- } catch (PackageManager.NameNotFoundException e) {
- }
- }
- try {
- final java.lang.ClassLoader cl = c.getClassLoader();
- //载入provider的类
- localProvider = (ContentProvider)cl.loadClass(info.name).newInstance();
- //得到该provider的IContentProvider对象
- provider = localProvider.getIContentProvider();
- localProvider.attachInfo(c, info);
- } catch (java.lang.Exception e) {
- }
- } else {
- //如果已经为该客户端创建过相应的provider,直接返回即可
- provider = holder.provider;
- }
- IActivityManager.ContentProviderHolder retHolder;
- synchronized (mProviderMap) {
- IBinder jBinder = provider.asBinder();
- //重新构建ContentProviderHolder类型的retHolder
- if (localProvider != null) {
- ComponentName cname = new ComponentName(info.packageName, info.name);
- ProviderClientRecord pr = mLocalProvidersByName.get(cname);
- if (pr != null) {
- provider = pr.mProvider;
- } else {
- //得到ContentProvider的远程代理对象
- holder = new IActivityManager.ContentProviderHolder(info);
- holder.provider = provider;
- holder.noReleaseNeeded = true;
- pr = installProviderAuthoritiesLocked(provider, localProvider, holder);
- mLocalProviders.put(jBinder, pr);
- mLocalProvidersByName.put(cname, pr);
- }
- retHolder = pr.mHolder;
- } else {
- ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
- if (prc != null) {
- if (!noReleaseNeeded) {
- incProviderRefLocked(prc, stable);
- try {
- ActivityManagerNative.getDefault().removeContentProvider( holder.connection, stable);
- } catch (RemoteException e) {
- }
- }
- } else {
- ProviderClientRecord client = installProviderAuthoritiesLocked(provider, localProvider, holder);
- if (noReleaseNeeded) {
- prc = new ProviderRefCount(holder, client, 1000, 1000);
- } else {
- prc = stable
- ? new ProviderRefCount(holder, client, 1, 0)
- : new ProviderRefCount(holder, client, 0, 1);
- }
- mProviderRefCountMap.put(jBinder, prc);
- }
- retHolder = prc.holder;
- }
- }
- return retHolder;
- }
然后我们再回到ActivityThread中的acquireProvider():
- public final IContentProvider acquireProvider( Context c, String auth, int userId, boolean stable) {
- final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
- IActivityManager.ContentProviderHolder holder = null;
- try {
- //得到ContentProviderHolder对象
- holder = ActivityManagerNative.getDefault().getContentProvider( getApplicationThread(), auth, userId, stable);
- } catch (RemoteException ex) {
- }
- //用provider信息去初始化当前的provider
- holder = installProvider(c, holder, holder.info, true , holder.noReleaseNeeded, stable);
- //将得到provider代理对象返回给客户端调用
- return holder.provider;
- }
经过上面的分析,我们从最初的getContentResolver()一步步的分析,经过ContextImpl、ActivityThread、ActivityManagerNative、ActivityManagerService,最终得到了ContentProvider的代理对象。
三、ContentProvider调用分析
在上面一节中我们对getContentResolver()的过程进行分析,发现这样操作的结果不仅可以载入需要的ContentProvider(如果当前ContentProvider还没有被载入),并且调用了该ContentProvider的getIContentProvider()方法。这一节我们就要从这个方法入手,看看如何通过这个方法得到ContentProvider对象,又如何通过该对象传递对数据库的操作。我们先来看一下通过getIContentProvider()方法得到的究竟是什么对象。
- @ContentProvider.java
- public IContentProvider getIContentProvider() {
- return mTransport;
- }
- private Transport mTransport = new Transport();
- class Transport extends ContentProviderNative {
- ContentProvider getContentProvider() { }
- public String getProviderName() { }
- public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, ICancellationSignal cancellationSignal) { }
- public Uri insert(Uri uri, ContentValues initialValues) { }
- public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) throws OperationApplicationException { }
- public int delete(Uri uri, String selection, String[] selectionArgs) { }
- public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { }
- }
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- enforceWritePermission(uri);
- return ContentProvider.this.delete(uri, selection, selectionArgs);
- }
- public abstract int delete(Uri uri, String selection, String[] selectionArgs);
我们此时来看一下ContentProvider本身提供了哪些重要的方法:
- public abstract class ContentProvider implements ComponentCallbacks2 {
- private Transport mTransport = new Transport();
- //构造函数
- public ContentProvider() { }
- //权限相关操作
- protected final void setReadPermission(String permission) { }
- public final String getReadPermission() { }
- protected final void setWritePermission(String permission) { }
- public final String getWritePermission() { }
- //增、删、改、查操作。
- public abstract Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder);
- public abstract Uri insert(Uri uri, ContentValues values);
- public abstract int delete(Uri uri, String selection, String[] selectionArgs);
- public abstract int update(Uri uri, ContentValues values, String selection, String[] selectionArgs);
- public IContentProvider getIContentProvider() { }
- public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) throws OperationApplicationException { }
- }
此时我们结合Transport来分析不难发现,这个Transport对象作为ContentProvider的代理,可以对此对象发起各项请求。该代理得到请求后,就会把请求“转发”给ContentProvider本身。
结合上一节我们分析的内容,我们可以总结如下:
我们在应用层调用getContentResolver().delete()的操作,将会调用到ContentResolver对象的delete操作,而ContentResolver对象就相当于通过getIContentProvider()得到的Transport对象,而Transport对象作为ContentProvider的代理将会把各项请求转移到ContentProvider中,因此就调用到ContentProvider的delete方法。
getContentResolver==>ContentResolver==>Transport==>ContentProvider
四、ContentProvider到ContactsProvider
4.1、ContactsProvider综览
经过上面的过程,我们把操作转移到了ContentProvider中,接下来我们需要借助具体的provider来继续分析, 我们挑选联系人数据库(ContactsProvider)作为示例来研究。联系人数据库源码位于\packages\providers\ContactsProvider\中,我们先来看一下他的AndroidManifest.xml文件:
- @AndroidManifest.xml
- <provider android:name="ContactsProvider2"
- android:authorities="contacts;com.android.contacts"
- android:label="@string/provider_label"
- android:multiprocess="false"
- android:exported="true"
- android:readPermission="android.permission.READ_CONTACTS"
- android:writePermission="android.permission.WRITE_CONTACTS">
- <path-permission
- android:pathPrefix="/search_suggest_query"
- android:readPermission="android.permission.GLOBAL_SEARCH" />
- <path-permission
- android:pathPrefix="/search_suggest_shortcut"
- android:readPermission="android.permission.GLOBAL_SEARCH" />
- <path-permission
- android:pathPattern="/contacts/.*/photo"
- android:readPermission="android.permission.GLOBAL_SEARCH" />
- <grant-uri-permission android:pathPattern=".*" />
- </provider>
4.2、ContactsProvider结构
ContactsProvider结构中涉及到五个重要的类:ContentProvider、SQLiteTransactionListener、AbstractContactsProvider、ContactsProvider2、ProfileProvider。下面我们先简单说一下他们的关系。ContactsProvider在ContentProvider的基础上与SQLiteTransactionListener结合共同组件了AbstractContactsProvider,这是ContactsProvider最基础的类,然后在AbstractContactsProvider的基础上,扩展出来了ContactsProvider2和ProfileProvider这两个类,如下图所示:
接下来我们来分别介绍这五个类的作用。
4.2.1、ContactsProvider
这个不用多说,是系统提供的ContactsProvider架构,里面遗留了对数据库操作的接口,需要子类去实现。4.2.2、SQLiteTransactionListener
这是一个接口,里面内容也比较简单,只有3个方法:- public interface SQLiteTransactionListener {
- /**
- * Called immediately after the transaction begins.
- */
- void onBegin();
- /**
- * Called immediately before commiting the transaction.
- */
- void onCommit();
- /**
- * Called if the transaction is about to be rolled back.
- */
- void onRollback();
- }
4.2.3、AbstractContactsProvider
这是ContactsProvider结构中最底层的类,我们来看一下他内部主要的方法:- public abstract class AbstractContactsProvider extends ContentProvider implements SQLiteTransactionListener {
- public SQLiteOpenHelper getDatabaseHelper() { }
- public Uri insert(Uri uri, ContentValues values) { }
- public int delete(Uri uri, String selection, String[] selectionArgs) { }
- public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { }
- public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) { }
- private ContactsTransaction startTransaction(boolean callerIsBatch) { }
- private void endTransaction(boolean callerIsBatch) { }
- protected abstract SQLiteOpenHelper getDatabaseHelper(Context context);
- protected abstract ThreadLocal<ContactsTransaction> getTransactionHolder();
- protected abstract Uri insertInTransaction(Uri uri, ContentValues values);
- protected abstract int deleteInTransaction(Uri uri, String selection, String[] selectionArgs);
- protected abstract int updateInTransaction(Uri uri, ContentValues values, String selection, String[] selectionArgs);
- protected abstract void notifyChange();
- }
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- //开始事务操作
- ContactsTransaction transaction = startTransaction(false);
- try {
- //用事务进行delete的操作
- int deleted = deleteInTransaction(uri, selection, selectionArgs);
- if (deleted > 0) {
- transaction.markDirty();
- }
- transaction.markSuccessful(false);
- return deleted;
- } finally {
- endTransaction(false);
- }
- }
- protected abstract int deleteInTransaction(Uri uri, String selection, String[] selectionArgs);
到这里我们发现,在AbstractContactsProvider中把insert、delete、update的操作转换成了事务的处理方式XXXInTransaction,并且把具体的实现留给了子类,这里的子类就是ContactsProvider2和ProfileProvider。也就是说, AbstractContactsProvider的作用就是把对数据库的操作转换成事务的处理方式,至于具体的事务操作,需要在其子类中实现 。
另外,我们注意到,所转换的只是insert、delete、update操作,而没有query的操作,也就是说,在ContentProvider中的query操作直接遗留给了子类的子类去实现,而跨过了AbstractContactsProvider的转换。这就说明, query的操作并不需要转换成事务的处理方式 。
4.2.4、ProfileProvider
我们现在来看ProfileProvider的结构:- public class ProfileProvider extends AbstractContactsProvider {
- public Cursor query(Uri uri,String[] projection,String selection,String[] selectionArgs,String sortOrder){}
- protected Uri insertInTransaction(Uri uri, ContentValues values){}
- protected int updateInTransaction(Uri uri, ContentValues values, String selection, String[] selectionArgs) {}
- protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs){}
- public void onBegin() { }
- public void onCommit() { }
- public void onRollback() { }
- }
这个问题我们待会儿就会明白。
4.2.5、ContactsProvider2
这是ContactsProvider中最重要也是最上层的类,当初我们在AndroidManifest中只对他进行了注册。我们来看一下他里面重要的方法:
- public class ContactsProvider2 extends AbstractContactsProvider implements OnAccountsUpdateListener {
- public Cursor query(Uri uri,String[] projection,String selection,String[] selectionArgs,String sortOrder) {}
- public int delete(Uri uri, String selection, String[] selectionArgs) {}
- public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {}
- public Uri insert(Uri uri, ContentValues values) {}
- protected Uri insertInTransaction(Uri uri, ContentValues values) {}
- protected int updateInTransaction(Uri uri, ContentValues values, String selection, String[] selectionArgs) {}
- protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) {}
- }
与ProfileProvider类似,他也提供了完整的数据访问、修改能力。
五、ContactsProvider与SQLite
我们需要明白一点,ContentProvider的底层仍然依靠SQLite来实现的,ContentProvider只是将SQLite的操作进行了封装,更容易操作和理解。
在ContactsProvider的底层设计上,ContactsDatabaseHelper承担着与SQLite直接沟通的角色,在此之上又有差异化扩展了ProfileDatabaseHelper这个类。因此可以认为,在ContactsProvider的底层有两个与SQLite的帮助类。先来看一下他们的结构:
- public class ProfileDatabaseHelper extends ContactsDatabaseHelper {}
- public class ContactsDatabaseHelper extends SQLiteOpenHelper {}
这两个SQLiteOpenHelper类均是在ContactsProvider2的onCreate()时被初始化的:
- public boolean onCreate() {
- super.onCreate();
- return initialize();
- }
- private boolean initialize() {
- //初始化ContactsDatabaseHelper
- mContactsHelper = getDatabaseHelper(getContext());
- mDbHelper.set(mContactsHelper);
- //初始化ProfileDatabaseHelper
- mProfileHelper = mProfileProvider.getDatabaseHelper(getContext());
- return true;
- }
- protected ContactsDatabaseHelper getDatabaseHelper(final Context context) {
- return ContactsDatabaseHelper.getInstance(context);
- }
- @ContactsDatabaseHelper.java
- public static synchronized ContactsDatabaseHelper getInstance(Context context) {
- if (sSingleton == null) {
- //new出一个ContactsDatabaseHelper完成初始化
- sSingleton = new ContactsDatabaseHelper(context, DATABASE_NAME, true);
- }
- return sSingleton;
- }
- protected ProfileDatabaseHelper getDatabaseHelper(Context context) {
- return ProfileDatabaseHelper.getInstance(context);
- }
- public static synchronized ProfileDatabaseHelper getInstance(Context context) {
- if (sSingleton == null) {
- //new出一个ProfileDatabaseHelper完成初始化
- sSingleton = new ProfileDatabaseHelper(context, DATABASE_NAME, true);
- }
- return sSingleton;
- }
既然SQLiteOpenHelper存在两个,配套的,应该就有两个ContentProvider去操作这两个SQLiteOpenHelper,事实确实如此,在这两个SQLite操作类之上,分别搭建了ProfileProvider与ContactsProvider2这两个与ContentProvider相关的类,也就是说,这四者的对应关系类似与下图:
下面我们借助一次delete()操作来看看这两对数据库的操作流向。
5.1、仍然继续delete()
我们不妨再次回顾一下,当我们进行delete操作时,我们调用getContentResolver最终将会调用到ContentProvider中的delete方法,进而调用到ContactsProvider2中的delete方法:- @ContactsProvider2.java
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- waitForAccess(mWriteAccessLatch);
- //权限管理
- enforceSocialStreamWritePermission(uri);
- //查看是否需要放到ProfileProvider中处理
- if (mapsToProfileDb(uri)) {
- switchToProfileMode();
- //在ProfileProvider中处理
- return mProfileProvider.delete(uri, selection, selectionArgs);
- } else {
- switchToContactMode();
- //回到父类中处理delete操作
- return super.delete(uri, selection, selectionArgs);
- }
- }
- private boolean mapsToProfileDb(Uri uri) {
- return sUriMatcher.mapsToProfile(uri);
- }
- @ContactsProvider2.java
- static {
- final UriMatcher matcher = sUriMatcher;
- matcher.addURI(ContactsContract.AUTHORITY, "contacts", CONTACTS);
- matcher.addURI(ContactsContract.AUTHORITY, "contacts/#", CONTACTS_ID);
- matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/data", CONTACTS_ID_DATA);
- matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/entities", CONTACTS_ID_ENTITIES);
- matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions", AGGREGATION_SUGGESTIONS);
- matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/suggestions/*", AGGREGATION_SUGGESTIONS);
- matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/photo", CONTACTS_ID_PHOTO);
- matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/display_photo", CONTACTS_ID_DISPLAY_PHOTO);
- matcher.addURI(ContactsContract.AUTHORITY, "contacts/#/stream_items", CONTACTS_ID_STREAM_ITEMS);
- matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter", CONTACTS_FILTER);
- matcher.addURI(ContactsContract.AUTHORITY, "contacts/filter/*", CONTACTS_FILTER);
- matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*", CONTACTS_LOOKUP);
- matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/data", CONTACTS_LOOKUP_DATA);
- matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/photo", CONTACTS_LOOKUP_PHOTO);
- matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#", CONTACTS_LOOKUP_ID);
- matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/data", CONTACTS_LOOKUP_ID_DATA);
- matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/#/photo", CONTACTS_LOOKUP_ID_PHOTO);
- matcher.addURI(ContactsContract.AUTHORITY, "contacts/lookup/*/display_photo", CONTACTS_LOOKUP_DISPLAY_PHOTO);
- //......
- }
下面我们分别看这两种情况具体的操作。
5.2、ContactsProvider2的操作
我们先来分析这个数据流操作,再去分析ProfileProvider操作。也就是说我们需要switchToContactMode():
- private void switchToContactMode() {
- //将mDbHelper切换到mContactsHelper,也就是ContactsDatabaseHelper
- mDbHelper.set(mContactsHelper);
- mTransactionContext.set(mContactTransactionContext);
- mAggregator.set(mContactAggregator);
- mPhotoStore.set(mContactsPhotoStore);
- mInProfileMode.set(false);
- }
- @AbstractContactsProvider.java
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- ContactsTransaction transaction = startTransaction(false);
- try {
- int deleted = deleteInTransaction(uri, selection, selectionArgs);
- transaction.markSuccessful(false);
- return deleted;
- } finally {
- endTransaction(false);
- }
- }
- protected abstract int deleteInTransaction(Uri uri, String selection, String[] selectionArgs);
- protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) {
- //得到SQLiteOpenHelper,当前是ContactsDatabaseHelper
- final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
- //根据当前uri匹配结果
- final int match = sUriMatcher.match(uri);
- switch (match) {
- case CONTACTS: {
- invalidateFastScrollingIndexCache();
- return 0;
- }
- case CONTACTS_ID: {
- invalidateFastScrollingIndexCache();
- long contactId = ContentUris.parseId(uri);
- return deleteContact(contactId, callerIsSyncAdapter);
- }
- default: {
- mSyncToNetwork = true;
- return mLegacyApiSupport.delete(uri, selection, selectionArgs);
- }
- }
- }
- private int deleteContact(long contactId, boolean callerIsSyncAdapter) {
- //得到SQLiteOpenHelper
- final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
- mSelectionArgs1[0] = Long.toString(contactId);
- //先查询相关信息
- Cursor c = db.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID}, RawContacts.CONTACT_ID + "=?", mSelectionArgs1, null, null, null);
- try {
- while (c.moveToNext()) {
- long rawContactId = c.getLong(0);
- markRawContactAsDeleted(db, rawContactId, callerIsSyncAdapter);
- }
- } finally {
- c.close();
- }
- mProviderStatusUpdateNeeded = true;
- //删除SQLite
- return db.delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null);
- }
我们详细看一下SQLiteDatabase的delete()过程:
- @SQLiteDatabase.java
- public int delete(String table, String whereClause, String[] whereArgs) {
- acquireReference();
- try {
- //构建SQL语句
- SQLiteStatement statement = new SQLiteStatement(this, "DELETE FROM " + table + (!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs);
- try {
- //执行删除命令
- return statement.executeUpdateDelete();
- } finally {
- statement.close();
- }
- } finally {
- releaseReference();
- }
- }
到这里,我们终于完成了从ContentProvider到SQLite的“历程”。
5.3、ProfileProvider的操作
首先要切换数据库为ProfileDatabaseHelper:- private void switchToProfileMode() {
- //为mDbHelper设置ProfileDatabaseHelper
- mDbHelper.set(mProfileHelper);
- mTransactionContext.set(mProfileTransactionContext);
- mAggregator.set(mProfileAggregator);
- mPhotoStore.set(mProfilePhotoStore);
- mInProfileMode.set(true);
- }
- mProfileProvider.delete(uri, selection, selectionArgs);
- @AbstractContactsProvider.java
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- ContactsTransaction transaction = startTransaction(false);
- try {
- //把delete转换为事务的处理方式
- int deleted = deleteInTransaction(uri, selection, selectionArgs);
- if (deleted > 0) {
- transaction.markDirty();
- }
- transaction.markSuccessful(false);
- return deleted;
- } finally {
- endTransaction(false);
- }
- }
- protected abstract int deleteInTransaction(Uri uri, String selection, String[] selectionArgs);
- @ProfileProvider.java
- protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) {
- enforceWritePermission();
- useProfileDbForTransaction();
- return mDelegate.deleteInTransaction(uri, selection, selectionArgs);
- }
这里的mDelegate就是ContactsProvider2本身,因此在ProfileProvider中扰了一圈,又回到了ContactsProvider2中的deleteInTransaction(),而这个方法我们在5.2节已经介绍过详细的流程。
六、总结
现在我们回顾一下整个流程:
1、当我们调用getContentResolver().delete()后,将会通过getContentResolver()得到ContentResolver对象,然后调用该对象的delete()方法。
2、在ContentResolver中,会通过acquireProvider()的方法得到IContentProvider对象,而这个对象的获取首先需要ActivityThread中向ActivityManagerService申请的ContentProvider的详细信息(ContentProviderHolder),然后利用这个Holder去得到(getIContentProvider)ContentProvider的远程代理对象(Transport对象)。
3、拿到这个对象之后,调用其delete方法,该方法将会由ContentProvider传递给其子类(AbstractContactsProvider),并在子类中将delete操作转换为事务处理的方式(deleteInTransaction),AbstractContactsProvider中虽然将处理方式转换成事务的方式,但是却没有具体的实现,而是把具体的操作留给其子类(ContactsProvider2)完成。
4、ContactsProvider2在实现过程中将会用相应的SQLiteOpenHelper去把操作转换成具体的SQLite语句并执行。
下面我们用一张图来结束本次的学习。
-
顶
- 0
-
踩