热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

深入解析Android联系人数据库设计:AbstractContactsProvider

本文探讨了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类的核心功能,包括事务管理和批处理操作的支持。通过这种方式,可以有效地管理复杂的数据库操作,确保数据的一致性和完整性。


推荐阅读
  • Windows服务与数据库交互问题解析
    本文探讨了在Windows 10(64位)环境下开发的Windows服务,旨在定期向本地MS SQL Server (v.11)插入记录。尽管服务已成功安装并运行,但记录并未正确插入。我们将详细分析可能的原因及解决方案。 ... [详细]
  • 深入解析Android自定义View面试题
    本文探讨了Android Launcher开发中自定义View的重要性,并通过一道经典的面试题,帮助开发者更好地理解自定义View的实现细节。文章不仅涵盖了基础知识,还提供了实际操作建议。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ... [详细]
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • 1.如何在运行状态查看源代码?查看函数的源代码,我们通常会使用IDE来完成。比如在PyCharm中,你可以Ctrl+鼠标点击进入函数的源代码。那如果没有IDE呢?当我们想使用一个函 ... [详细]
  • 深入理解 SQL 视图、存储过程与事务
    本文详细介绍了SQL中的视图、存储过程和事务的概念及应用。视图为用户提供了一种灵活的数据查询方式,存储过程则封装了复杂的SQL逻辑,而事务确保了数据库操作的完整性和一致性。 ... [详细]
  • 本文深入探讨 MyBatis 中动态 SQL 的使用方法,包括 if/where、trim 自定义字符串截取规则、choose 分支选择、封装查询和修改条件的 where/set 标签、批量处理的 foreach 标签以及内置参数和 bind 的用法。 ... [详细]
  • 本文详细介绍了Java中org.eclipse.ui.forms.widgets.ExpandableComposite类的addExpansionListener()方法,并提供了多个实际代码示例,帮助开发者更好地理解和使用该方法。这些示例来源于多个知名开源项目,具有很高的参考价值。 ... [详细]
  • 使用 Azure Service Principal 和 Microsoft Graph API 获取 AAD 用户列表
    本文介绍了一段通用代码示例,该代码不仅能够操作 Azure Active Directory (AAD),还可以通过 Azure Service Principal 的授权访问和管理 Azure 订阅资源。Azure 的架构可以分为两个层级:AAD 和 Subscription。 ... [详细]
  • PyCharm下载与安装指南
    本文详细介绍如何从官方渠道下载并安装PyCharm集成开发环境(IDE),涵盖Windows、macOS和Linux系统,同时提供详细的安装步骤及配置建议。 ... [详细]
  • c# – UWP:BrightnessOverride StartOverride逻辑 ... [详细]
  • 数据库内核开发入门 | 搭建研发环境的初步指南
    本课程将带你从零开始,逐步掌握数据库内核开发的基础知识和实践技能,重点介绍如何搭建OceanBase的开发环境。 ... [详细]
  • 本文详细介绍了如何使用 Yii2 的 GridView 组件在列表页面实现数据的直接编辑功能。通过具体的代码示例和步骤,帮助开发者快速掌握这一实用技巧。 ... [详细]
author-avatar
王乐668_802
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有