您的位置:首页 > 编程语言 > PHP开发

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 ContentProvider