作者:王乐668_802 | 来源:互联网 | 2024-11-24 18:04
本文探讨了Android系统中联系人数据库的设计,特别是AbstractContactsProvider类的作用与实现。文章提供了对源代码的详细分析,并解释了该类如何支持跨数据库操作及事务处理。源代码可从官方Android网站下载。
本文旨在深入探讨Android系统中联系人数据库的设计,尤其是AbstractContactsProvider类的关键作用及其内部实现机制。通过本文,读者可以了解该类如何有效地管理跨数据库操作及事务处理,从而提高应用性能和数据安全性。
AbstractContactsProvider是联系人和用户资料提供者的公共基类,它不仅处理了SQLiteContentProvider中类似的数据库逻辑,还向子类暴露了批处理操作的支持,以便能够处理跨数据库的操作。
package com.android.providers.contacts;
import android.content.ContentProvider;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteTransactionListener;
import android.net.Uri;
import java.util.ArrayList;
/**
* AbstractContactsProvider是联系人和用户资料提供者的公共基类。它处理了SQLiteContentProvider中的大部分相同逻辑,
* 同时向子类暴露了批处理操作的支持,以实现跨数据库操作。
*/
public abstract class AbstractContactsProvider extends ContentProvider implements SQLiteTransactionListener {
/**
* 在批处理操作成功释放锁后休眠的时间(毫秒)。
*/
protected static final int SLEEP_AFTER_YIELD_DELAY = 4000;
/**
* 单个批处理操作中允许的最大操作数。
*/
private static final int MAX_OPERATIONS_PER_YIELD_POINT = 500;
/**
* 在批处理操作中,每执行一定数量的插入操作后释放锁的数量。
*/
private static final int BULK_INSERTS_PER_YIELD_POINT = 50;
/**
* 当前线程活跃的联系人事务。
*/
private ThreadLocal mTransactionHolder;
/**
* 为此内容提供者使用的数据库帮助器。
*/
private SQLiteOpenHelper mDbHelper;
/**
* 用于序列化所有事务的数据库帮助器。如果非空,则此提供者创建的所有新事务都将自动从该帮助器获取一个可写的数据库实例并启动事务。
*/
private SQLiteOpenHelper mSerializeOnDbHelper;
/**
* 序列化事务的标签,与数据库对应。
*/
private String mSerializeDbTag;
@Override
public boolean onCreate() {
Context cOntext= getContext();
mDbHelper = getDatabaseHelper(context);
mTransactiOnHolder= getTransactionHolder();
return true;
}
public SQLiteOpenHelper getDatabaseHelper() {
return mDbHelper;
}
/**
* 设置用于序列化事务的数据库帮助器及其对应的标签。
* @param serializeOnDbHelper 用于序列化事务的数据库帮助器。
* @param tag 对应数据库的标签。
*/
public void setDbHelperToSerializeOn(SQLiteOpenHelper serializeOnDbHelper, String tag) {
mSerializeOnDbHelper= serializeOnDbHelper;
mSerializeDbTag = tag;
}
public ContactsTransaction getCurrentTransaction() {
return mTransactionHolder.get();
}
@Override
public Uri insert(Uri uri, ContentValues values) {
ContactsTransaction transaction = startTransaction(false);
try {
Uri result = insertInTransaction(uri, values);
if (result != null) {
transaction.markDirty();
}
transaction.markSuccessful(false);
return result;
} finally {
endTransaction(false);
}
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
ContactsTransaction transaction = startTransaction(false);
try {
int deleted = deleteInTransaction(uri, selection, selectionArgs);
if (deleted > 0) {
transaction.markDirty();
}
transaction.markSuccessful(false);
return deleted;
} finally {
endTransaction(false);
}
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
ContactsTransaction transaction = startTransaction(false);
try {
int updated = updateInTransaction(uri, values, selection, selectionArgs);
if (updated > 0) {
transaction.markDirty();
}
transaction.markSuccessful(false);
return updated;
} finally {
endTransaction(false);
}
}
@Override
public int bulkInsert(Uri uri, ContentValues[] values) {
ContactsTransaction transaction = startTransaction(true);
int numValues = values.length;
int opCount = 0;
try {
for (int i = 0; i insert(uri, values[i]);
if (++opCount >= BULK_INSERTS_PER_YIELD_POINT) {
opCount = 0;
try {
yield(transaction);
} catch (RuntimeException re) {
transaction.markYieldFailed();
throw re;
}
}
}
transaction.markSuccessful(true);
} finally {
endTransaction(true);
}
return numValues;
}
@Override
public ContentProviderResult[] applyBatch(ArrayList operations)
throws OperationApplicationException {
int ypCount = 0;
int opCount = 0;
ContactsTransaction transaction = startTransaction(true);
try {
final int numOperatiOns= operations.size();
final ContentProviderResult[] results = new ContentProviderResult[numOperations];
for (int i = 0; i if (++opCount >= MAX_OPERATIONS_PER_YIELD_POINT) {
throw new OperationApplicationException(
"Too many content provider operations between yield points. "
+ "The maximum number of operations per yield point is "
+ MAX_OPERATIONS_PER_YIELD_POINT, ypCount);
}
final ContentProviderOperation operation = operations.get(i);
if (i > 0 && operation.isYieldAllowed()) {
opCount = 0;
try {
if (yield(transaction)) {
ypCount++;
}
} catch (RuntimeException re) {
transaction.markYieldFailed();
throw re;
}
}
results[i] = operation.apply(this, results, i);
}
transaction.markSuccessful(true);
return results;
} finally {
endTransaction(true);
}
}
/**
* 如果当前没有事务,则启动一个新的事务,并设置线程局部事务变量进行跟踪。如果已经有一个事务,则返回该事务。
* @param callerIsBatch 调用者是否处于批处理模式。
*/
private ContactsTransaction startTransaction(boolean callerIsBatch) {
ContactsTransaction transaction = mTransactionHolder.get();
if (transaction == null) {
transaction = new ContactsTransaction(callerIsBatch);
if (mSerializeOnDbHelper != null) {
transaction.startTransactionForDb(mSerializeOnDbHelper.getWritableDatabase(),
mSerializeDbTag, this);
}
mTransactionHolder.set(transaction);
}
return transaction;
}
/**
* 结束当前事务并清除成员变量。这不会将事务标记为成功。
* @param callerIsBatch 调用者是否处于批处理模式。
*/
private void endTransaction(boolean callerIsBatch) {
ContactsTransaction transaction = mTransactionHolder.get();
if (transaction != null && (!transaction.isBatch() || callerIsBatch)) {
try {
if (transaction.isDirty()) {
notifyChange();
}
transaction.finish(callerIsBatch);
} finally {
mTransactionHolder.set(null);
}
}
}
/**
* 获取此联系人提供者使用的数据库帮助器。在onCreate()期间调用一次。
*/
protected abstract SQLiteOpenHelper getDatabaseHelper(Context context);
/**
* 获取用于跟踪事务的线程局部事务持有者。在onCreate()期间调用一次。如果多个类继承自此类并且需要在同一事务中保持同步,
* 它们必须返回相同的线程局部实例。
*/
protected abstract ThreadLocal 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 boolean yield(ContactsTransaction transaction);
protected abstract void notifyChange();
}
以上代码展示了AbstractContactsProvider类的核心功能,包括事务管理和批处理操作的支持。通过这种方式,可以有效地管理复杂的数据库操作,确保数据的一致性和完整性。