ContentProvider 源码分析---之三
2017-08-18 22:03
323 查看
3, ContentProvider实现
调用数据库的方法如下,ContentResolver resolver = getContentResolver();
Cursor phoneCursor = resolver.query(Phone.CONTENT_URI,•••
实际步骤如下,
1,调用getContentResolver方法获取ContextImpl的内部类ApplicationContentResolver对象;
2,通过ApplicationContentResolver对象获取目标ContentProvider的Transport对象(IContentProvider对象).
如果目标ContentProvider已启动,直接在AMS中的变量查询获取并返回;
如果目标ContentProvider未启动,但所在进程已创建,则安装ContentProvider;
如果目标ContentProvider所在进程未创建,则先创建进程。
3,通过IContentProvider对象调用增删改查方法。
insert/delete/update/query四个方法调用流程图完全相同,以delete为例论述,
客户端调用目标ContentProvider的delete方法其实就是Transport的delete方法,
Transport的delete方法调用流程图如下,
Transport的delete方法如下,
@Override public int delete(String callingPkg, Uri uri, String selection, String[] selectionArgs) { validateIncomingUri(uri); uri = getUriWithoutUserId(uri); if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) { return 0; } final String original = setCallingPackage(callingPkg); try { return ContentProvider.this.delete(uri, selection, selectionArgs); } finally { setCallingPackage(original); } }
ContentProvider的delete方法是一个抽象方法,由各个子类去实现,
public abstract int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs);
这样,就调用到了ContentProvider的delete方法。
4, ContactsProvider分析
调用联系人的删除方法,就会调用到ContactsProvider2的delete方法。ContactsProvider2的oncreate方法在此就不论述了。
ContactsProvider2的oncreate方法如下,
public int delete(Uri uri, String selection, String[] selectionArgs) { waitForAccess(mWriteAccessLatch); if (mapsToProfileDb(uri)) { switchToProfileMode(); return mProfileProvider.delete(uri, selection, selectionArgs); } switchToContactMode(); return super.delete(uri, selection, selectionArgs); }
在delete的过程中,根据mapsToProfileDb()的判断,需要切换两种模式:Profile与Contact模式,需要根据不同的
情况切换不同的SQLiteOpenHelper去操作数据库。
mapsToProfileDb方法如下,
private boolean mapsToProfileDb(Uri uri) {
return sUriMatcher.mapsToProfile(uri);
}
根据给出的uri去sUriMatcher中查找是否有匹配的项,如果有,就认为需要转换到Profile模式去处理,那么sUriMatcher中
究竟有哪些项呢?
在ContactsProvider2的static代码块中,
static { // Contacts URI matching table 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); •••
4.1 小节论述Contact模式;
4.2 小节论述Profile模式;
4.1 Contact模式
ContactsProvider2的delete方法有关Contact模式代码如下,switchToContactMode(); return super.delete(uri, selection, selectionArgs);
首先切换到Contact模式,然后调用父类AbstractContactsProvider的delete方法。
switchToContactMode方法如下,
private void switchToContactMode() { if (ENABLE_TRANSACTION_LOG) { Log.i(TAG, "switchToContactMode", new RuntimeException("switchToContactMode")); } //将mDbHelper切换到mContactsHelper,也就是ContactsDatabaseHelper mDbHelper.set(mContactsHelper); mTransactionContext.set(mContactTransactionContext); mAggregator.set(mContactAggregator); mPhotoStore.set(mContactsPhotoStore); mInProfileMode.set(false); }
AbstractContactsProvider的delete方法调用流程图如下,
AbstractContactsProvider的delete方法如下,
ContactsTransaction transaction = startTransaction(false); //事务操作,获取ContactsTransaction对象 try { int deleted = deleteInTransaction(uri, selection, selectionArgs); //用事务进行delete的操作
deleteInTransaction是一个抽象方法, ContactsProvider2中实现逻辑如下,
1,根据URI匹配结果,
final SQLiteDatabase db = mDbHelper.get().getWritableDatabase(); flushTransactionalChanges(); final boolean callerIsSyncAdapter = readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false); final int match = sUriMatcher.match(uri);
2,根据不同的结果分别进行处理,
在此以CONTACTS_ID进行论述,
case CONTACTS_ID: { invalidateFastScrollingIndexCache(); long contactId = ContentUris.parseId(uri); return deleteContact(contactId, callerIsSyncAdapter); }
deleteContact方法逻辑如下,
1,获取SQLiteDatabase对象,
final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
当前来说就是得到ContactsDatabaseHelper的SQLiteDatabase对象。
2,查询相关信息, 遍历每一项标记其删除的标记
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(); }
3,调用ContactsTableUtil的deleteContact完成删除动作,
int result = ContactsTableUtil.deleteContact(db, contactId);
ContactsTableUtil的deleteContact方法如下,
public static int deleteContact(SQLiteDatabase db, long contactId) { DeletedContactsTableUtil.insertDeletedContact(db, contactId); return db.delete(Tables.CONTACTS, Contacts._ID + " = ?", new String[]{contactId + ""}); }
直接调用SQLiteDatabase的delete方法,该方法如下,
public int delete(String table, String whereClause, String[] whereArgs) { acquireReference(); try { SQLiteStatement statement = new SQLiteStatement(this, "DELETE FROM " + table + (!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs); try { return statement.executeUpdateDelete(); } finally { statement.close(); } } finally { releaseReference(); } }
通过SQLiteStatement生成SQL语句(DELETE FROM XXX WHERE XXX),然后通过executeUpdateDelete()方法去应用该SQL操作,
从而完成delete的操作。
4.2 Profile模式
ContactsProvider2的delete方法有关Contact模式代码如下,switchToProfileMode(); return mProfileProvider.delete(uri, selection, selectionArgs);
首先切换到Profile模式,然后调用ProfileProvider的delete方法。
switchToProfileMode方法如下,
private void switchToProfileMode() { if (ENABLE_TRANSACTION_LOG) { Log.i(TAG, "switchToProfileMode", new RuntimeException("switchToProfileMode")); } mDbHelper.set(mProfileHelper); mTransactionContext.set(mProfileTransactionContext); mAggregator.set(mProfileAggregator); mPhotoStore.set(mProfilePhotoStore); mInProfileMode.set(true); }
ProfileProvider也是继承于AbstractContactsProvider方法,调用流程图如下,
delete方法也是在父类AbstractContactsProvider中实现的。
ProfileProvider的deleteInTransaction方法如下,
protected int deleteInTransaction(Uri uri, String selection, String[] selectionArgs) { useProfileDbForTransaction(); return mDelegate.deleteInTransaction(uri, selection, selectionArgs); }
mDelegate是ContactsProvider2对象,因此,最后还是调用ContactsProvider2的deleteInTransaction实现。
因此,在联系人数据库中,虽然分为2种模式,但是最后都是通过Contacts模式来实现的。并且,最后调用
SQLiteDatabase的方法进行数据库的操作。
相关文章推荐
- [置顶] Android 双开沙箱 VirtualApp 源码分析(六)ContentProvider
- ContentProvider源码分析
- ContentProvider源码分析
- ContentProvider源码分析(原)
- ContentProvider 源码分析---之一
- ContentProvider源码分析
- Android 5.0源码分析---ContentProvider中的ContentObserver研究
- ContentProvider 源码分析---之二
- 基于N源码的ContentProvider调用流程分析
- Android之ContentProvider的启动过程源码分析
- ContentProvider源码分析(原)
- ContentProvider源码分析
- ContentProvider源码分析
- EventBus 3 源码分析
- strcspn源码分析
- 为什么HashSet不能重复以及具体原理源码分析
- RankLib源码分析(三)----LambdaRank
- Jafka源码分析——LogManager
- Universal-Image-Loader(UIL)使用方法&流程图&源码分析 ----- 未完
- redis源码分析之配置文件