getContentResolver().delete();这个简单的操作其实包含了两个步骤:
下面我们就开启此次漫长的旅程。
为了解答这两个问题,我们需要从代码的最源头开始分析:
@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的呢?
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操作去分析,看两者究竟有什么关系。
@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方法。
接下来所介绍的流程,比较复杂,各位看好了。
@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,下面我们来分析这个创建的过程。
ActivityManagerNative.getDefault().getContentProvider( getApplicationThread(), auth, userId, stable);
这个过程可以分为两步:
1、我们来看通过ActivityManagerNative.getDefault()所得到的对象;
2、我们再来分析这个对象的getContentProvider方法。
@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", new DbBinder(m)); } catch (PackageManager.NameNotFoundException e) { } }我们再来看ActivityManagerService的继承关系:
public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {}说明这个Server继承自ActivityManagerNative,而且父类主要完成一些Binder的操作。
@ActivityManagerNative.java static public IActivityManager getDefault() { return gDefault.get(); }我们看,调用ActivityManagerNative的getDefault()方法的结果就是得到gDefault对象里面的数据,那么gDefault里面究竟放着怎样的数据呢?我们来看他的定义:
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() { protected IActivityManager create() { IBinder b = ServiceManager.getService("activity"); IActivityManager am = asInterface(b); return am; } };原来,在gDefault变量的初始化过程中(create),完成了两步重要的操作:
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); }通过asInterface()的细节我们发现, 我们得到的远程代理对象就是ActivityManagerProxy对象。也就是说我们当初的:
ActivityManagerNative.getDefault().getContentProvider( getApplicationThread(), auth, userId, stable);其实相当于:
ActivityManagerProxy.getContentProvider(getApplicationThread(), auth, userId, stable);;现在我们已经弄明白了2.4中提到的第一步操作,下面我们来分析第二部操作。
@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; } }我们看到,在getContentProvider的过程中,ActivityManagerProxy把请求通过mRemote发送给远端的ActivityManagerNative去处理,请求码为GET_CONTENT_PROVIDER_TRANSACTION。
@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; } } } }在onTransact中把该请求又发送给了真正的服务端ActivityManagerService.getContentProvider():
@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; }在上面这个过程中,我们发现, 在ActivityManagerService中有存在着一个mProviderMap的变量用于保存当前系统中所有的provider,其中每一项都是一个ContentProviderRecord型的数据,通过这个数据可以完成两个重要作用:
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; }在前面的过程中,我们通过ActivityManagerService得到了ContentProviderHolder对象,该对象是对provider的详细描述, 下面我们需要用这些描述在installProvider()方法中开启provider,并获得该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; }我们清晰的看到,在installProvider的方法中,我们 用ActivityManagerService中得到的ContentProvider信息,去加载该ContentProvider(localProvider),并调用他的getIContentProvider()方法得到该provider的代理对象。
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.java public IContentProvider getIContentProvider() { return mTransport; }这里得到的只是IContentProvider类型的mTransport变量,而这个变量的来历呢?
private Transport mTransport = new Transport();这就说明,通过getIContentProvider()的方法得到的只是Transport对象,他是ContentProvider的内部类:
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) { } }而且我们发现这个内部类提供了用于查询数据库的各项操作。那么当我们进行delete操作的时候呢?
public int delete(Uri uri, String selection, String[] selectionArgs) { enforceWritePermission(uri); return ContentProvider.this.delete(uri, selection, selectionArgs); }既然Transport内部把delete操作传递给了ContentProvider去操作,那么我们就来看看ContentProvider本身对delete()的处理:
public abstract int delete(Uri uri, String selection, String[] selectionArgs);这里我们遇到了抽象的方法,也就是说,delete操作的具体细节需要在ContentProvider的子类中实现了,这也符合ContentProvider框架的设计理念,即: ContentProvider负责抽象部分的表述,具体的操作需要各自private自己去实现。
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 { } }从ContentProvider提供的方法我们发现,除了权限管理类的方法外,其他的就是一些与delete类似的、与数据库处理相关的抽象方法。
我们在应用层调用getContentResolver().delete()的操作,将会调用到ContentResolver对象的delete操作,而ContentResolver对象就相当于通过getIContentProvider()得到的Transport对象,而Transport对象作为ContentProvider的代理将会把各项请求转移到ContentProvider中,因此就调用到ContentProvider的delete方法。
getContentResolver==>ContentResolver==>Transport==>ContentProvider
@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>这段声明告诉系统该provider的name、authorities、permission等信息,简单来说,这个数据库的名字叫做ContactsProvider2,可以通过contacts或者com.android.contacts的前缀来匹配,而且访问这个数据库需要相应的权限READ_CONTACTS、WRITE_CONTACTS等。
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(); }从注释中可以看出,他主要提供与事务处理相关的回调方法,其中onBegin是事务开始处理之后时调用的回调函数,onCommit是事务提交之后的回调函数,onRollback是事务回滚时的回调函数,由此推断, 在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(); }这些方法都很好理解,均是对数据库的各项操作。还记得我们在分析ContentProvider的delete操作时提到,ContentProvider把对数据库的各项操作放到子类中处理,对当前环境来说,就是需要在AbstractContactsProvider中处理的,因此delete的操作就应该调用的这里:
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); } }继续看deleteInTransaction的实现:
protected abstract int deleteInTransaction(Uri uri, String selection, String[] selectionArgs);这仍然是个虚函数,具体定义需要留给子类去实现。
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() { } }我们从ProfileProvider的结构看出,他具备独立的query操作,以及插入、删除、更新的事务操作,以及事务相关的回调函数,可以说,他具备了完整的数据访问、修改能力。但是他的作用呢?
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类似,他也提供了完整的数据访问、修改能力。
我们需要明白一点,ContentProvider的底层仍然依靠SQLite来实现的,ContentProvider只是将SQLite的操作进行了封装,更容易操作和理解。
在ContactsProvider的底层设计上,ContactsDatabaseHelper承担着与SQLite直接沟通的角色,在此之上又有差异化扩展了ProfileDatabaseHelper这个类。因此可以认为,在ContactsProvider的底层有两个与SQLite的帮助类。先来看一下他们的结构:
public class ProfileDatabaseHelper extends ContactsDatabaseHelper {} public class ContactsDatabaseHelper extends SQLiteOpenHelper {}继承关系如下:
public boolean onCreate() { super.onCreate(); return initialize(); } private boolean initialize() { //初始化ContactsDatabaseHelper mContactsHelper = getDatabaseHelper(getContext()); mDbHelper.set(mContactsHelper); //初始化ProfileDatabaseHelper mProfileHelper = mProfileProvider.getDatabaseHelper(getContext()); return true; }我们先看ContactsDatabaseHelper初始化过程:
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; }再来看ProfileDatabaseHelper初始化过程:
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; }因为在ContactsProvider中存在两个“不同”的SQLiteOpenHelper,因此在具体的数据库操作时,需要根据不同需要来切换(switchToXXXMode)不同的SQLiteOpenHelper去操作。切换的过程我们稍后再讲。
下面我们借助一次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); } }在delete的过程中,根据mapsToProfileDb()的判断,需要切换两种模式:Profile与Contact模式,这也是我们刚刚讲的,需要根据不同的情况切换不同的SQLiteOpenHelper去操作数据库,我们现在来看一下区分两种模式的依据:
private boolean mapsToProfileDb(Uri uri) { return sUriMatcher.mapsToProfile(uri); }这里是根据给出的uri去sUriMatcher中查找是否有匹配的项,如果有,就认为需要转换到Profile模式去处理,那么sUriMatcher中究竟有哪些项呢?
@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); //...... }我们发现,在ContactsContract中定义的URI都在这个MAP中,也就是说,我们用ContactsContract中的URI去操作数据库时,都应该满足mapsToProfileDb的条件。
下面我们分别看这两种情况具体的操作。
我们先来分析这个数据流操作,再去分析ProfileProvider操作。也就是说我们需要switchToContactMode():
private void switchToContactMode() { //将mDbHelper切换到mContactsHelper,也就是ContactsDatabaseHelper mDbHelper.set(mContactsHelper); mTransactionContext.set(mContactTransactionContext); mAggregator.set(mContactAggregator); mPhotoStore.set(mContactsPhotoStore); mInProfileMode.set(false); }这里最重要的操作就是将mDbHelper中内容置换为mContactsHelper,也就是ContactsDatabaseHelper。接下来就是super.delete()的操作,这里的super对ContactsProvider2来说就是AbstractContactsProvider:
@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);这个“转换”的操作我们之前分析过,就是把delete操作转换为事务处理的方式,具体操作需要在子类中实现,因此又回到了ContactsProvider2中的deleteInTransaction:
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); } } }这里我们假设匹配的是CONTACTS_ID:
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); }在deleteContact的过程中,要先得到可用的SQLiteDatabase,当前来说就是得到ContactsDatabaseHelper的SQLiteDatabase,然后查询数据库得到Cursor,并遍历每一项标记其删除的标记,最后再调用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(); } }我们看到,delete操作中,先 通过SQLiteStatement生成SQL语句(DELETE FROM XXX WHERE XXX),然后通过executeUpdateDelete()方法去应用该SQL操作,从而完成delete的操作。
到这里,我们终于完成了从ContentProvider到SQLite的“历程”。
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);也就是调用ProfileProvider中的delete方法,但是在ProfileProvider没有找到delete方法,我们只能去其父类AbstractContactsProvider中调用delete():
@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);经过AbstractContactsProvider的“转换”,将delete操作转换到子类中的deleteInTransaction():
@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语句并执行。
下面我们用一张图来结束本次的学习。