深入分析 Android ContentProvider (六)

文章目录

    • 深入分析 Android ContentProvider (六)
    • ContentProvider 的性能优化和实践案例(续)
      • 1. 性能优化技巧(续)
        • 1.6. 使用批量插入优化性能
          • 示例:批量插入实现
        • 1.7. 使用 Projections 优化查询
          • 示例:使用 Projections
        • 1.8. 减少频繁通知
          • 示例:减少频繁通知
        • 1.9. 优化查询语句
          • 示例:优化查询语句
      • 2. 实践案例(续)
        • 2.3 案例三:联系人应用的数据管理
          • 联系人 ContentProvider 实现
        • 2.4 案例四:日历应用的数据管理
          • 日历 ContentProvider 实现
      • 3. 总结

深入分析 Android ContentProvider (六)

ContentProvider 的性能优化和实践案例(续)

在上一节中,我们介绍了 ContentProvider 的性能优化技巧和两个实际案例。本节将继续深入探讨更多的优化技巧,并提供更详细的实际案例分析。

1. 性能优化技巧(续)

1.6. 使用批量插入优化性能

在需要插入大量数据时,逐行插入会非常低效。可以使用 ContentProviderbulkInsert 方法进行批量插入,从而显著提升性能。

示例:批量插入实现
@Override
public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] values) {final SQLiteDatabase db = dbHelper.getWritableDatabase();switch (uriMatcher.match(uri)) {case MEDIA:db.beginTransaction();try {for (ContentValues value : values) {db.insertOrThrow(DatabaseHelper.TABLE_MEDIA, null, value);}db.setTransactionSuccessful();} finally {db.endTransaction();}getContext().getContentResolver().notifyChange(uri, null);return values.length;default:return super.bulkInsert(uri, values);}
}
1.7. 使用 Projections 优化查询

当查询数据库时,如果只需要部分字段,可以使用 Projections 来指定需要的列,以减少数据传输和内存消耗。

示例:使用 Projections
String[] projection = {DatabaseHelper.COLUMN_ID,DatabaseHelper.COLUMN_NAME
};Cursor cursor = getContentResolver().query(CONTENT_URI,    // Uriprojection,     // Projectionnull,           // Selectionnull,           // Selection argumentsnull            // Sort order
);
1.8. 减少频繁通知

在数据变化时,ContentProvider 会通知所有监听该 URI 的内容观察者。频繁的通知可能会导致性能问题。可以通过合并通知或使用 ContentResolver#notifyChange(Uri, ContentObserver, boolean) 的第三个参数控制通知范围。

示例:减少频繁通知
public int bulkUpdate(@NonNull Uri uri, @NonNull ContentValues[] values) {final SQLiteDatabase db = dbHelper.getWritableDatabase();db.beginTransaction();try {for (ContentValues value : values) {db.update(DatabaseHelper.TABLE_MEDIA, value, selection, selectionArgs);}db.setTransactionSuccessful();} finally {db.endTransaction();}getContext().getContentResolver().notifyChange(uri, null, false);return values.length;
}
1.9. 优化查询语句

复杂查询可能会降低性能,可以通过优化 SQL 语句,避免不必要的嵌套查询和表连接来提升性能。

示例:优化查询语句
Cursor cursor = db.query(DatabaseHelper.TABLE_MEDIA,projection,DatabaseHelper.COLUMN_NAME + " LIKE ?",new String[]{"%keyword%"},null,null,DatabaseHelper.COLUMN_NAME + " ASC"
);

2. 实践案例(续)

2.3 案例三:联系人应用的数据管理

在联系人应用中,管理联系人数据需要高效的数据存储和检索。ContentProvider 可以提供统一的接口来管理联系人数据,并通过批量操作和异步任务优化性能。

联系人 ContentProvider 实现
public class ContactsProvider extends ContentProvider {private static final String AUTHORITY = "com.example.contactsprovider";private static final String BASE_PATH = "contacts";public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH);private static final int CONTACTS = 1;private static final int CONTACT_ID = 2;private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);static {uriMatcher.addURI(AUTHORITY, BASE_PATH, CONTACTS);uriMatcher.addURI(AUTHORITY, BASE_PATH + "/#", CONTACT_ID);}private SQLiteDatabase database;@Overridepublic boolean onCreate() {DatabaseHelper dbHelper = new DatabaseHelper(getContext());database = dbHelper.getWritableDatabase();return true;}@Nullable@Overridepublic Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,@Nullable String[] selectionArgs, @Nullable String sortOrder) {switch (uriMatcher.match(uri)) {case CONTACTS:return database.query(DatabaseHelper.TABLE_CONTACTS, projection, selection, selectionArgs, null, null, sortOrder);case CONTACT_ID:selection = DatabaseHelper.COLUMN_ID + "=?";selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};return database.query(DatabaseHelper.TABLE_CONTACTS, projection, selection, selectionArgs, null, null, sortOrder);default:throw new IllegalArgumentException("Unknown URI: " + uri);}}@Nullable@Overridepublic Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {long id = database.insert(DatabaseHelper.TABLE_CONTACTS, null, values);getContext().getContentResolver().notifyChange(uri, null);return ContentUris.withAppendedId(CONTENT_URI, id);}@Overridepublic int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {int rowsDeleted;switch (uriMatcher.match(uri)) {case CONTACTS:rowsDeleted = database.delete(DatabaseHelper.TABLE_CONTACTS, selection, selectionArgs);break;case CONTACT_ID:selection = DatabaseHelper.COLUMN_ID + "=?";selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};rowsDeleted = database.delete(DatabaseHelper.TABLE_CONTACTS, selection, selectionArgs);break;default:throw new IllegalArgumentException("Unknown URI: " + uri);}getContext().getContentResolver().notifyChange(uri, null);return rowsDeleted;}@Overridepublic int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {int rowsUpdated;switch (uriMatcher.match(uri)) {case CONTACTS:rowsUpdated = database.update(DatabaseHelper.TABLE_CONTACTS, values, selection, selectionArgs);break;case CONTACT_ID:selection = DatabaseHelper.COLUMN_ID + "=?";selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};rowsUpdated = database.update(DatabaseHelper.TABLE_CONTACTS, values, selection, selectionArgs);break;default:throw new IllegalArgumentException("Unknown URI: " + uri);}getContext().getContentResolver().notifyChange(uri, null);return rowsUpdated;}@Nullable@Overridepublic String getType(@NonNull Uri uri) {switch (uriMatcher.match(uri)) {case CONTACTS:return "vnd.android.cursor.dir/vnd.com.example.contactsprovider.contacts";case CONTACT_ID:return "vnd.android.cursor.item/vnd.com.example.contactsprovider.contact";default:throw new IllegalArgumentException("Unknown URI: " + uri);}}
}
2.4 案例四:日历应用的数据管理

在日历应用中,管理事件和提醒需要高效的数据存储和检索。通过 ContentProvider,可以方便地管理日历数据,并通过缓存机制和异步操作优化性能。

日历 ContentProvider 实现
public class CalendarProvider extends ContentProvider {private static final String AUTHORITY = "com.example.calendarprovider";private static final String BASE_PATH = "events";public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH);private static final int EVENTS = 1;private static final int EVENT_ID = 2;private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);static {uriMatcher.addURI(AUTHORITY, BASE_PATH, EVENTS);uriMatcher.addURI(AUTHORITY, BASE_PATH + "/#", EVENT_ID);}private SQLiteDatabase database;@Overridepublic boolean onCreate() {DatabaseHelper dbHelper = new DatabaseHelper(getContext());database = dbHelper.getWritableDatabase();return true;}@Nullable@Overridepublic Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,@Nullable String[] selectionArgs, @Nullable String sortOrder) {switch (uriMatcher.match(uri)) {case EVENTS:return database.query(DatabaseHelper.TABLE_EVENTS, projection, selection, selectionArgs, null, null, sortOrder);case EVENT_ID:selection = DatabaseHelper.COLUMN_ID + "=?";selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};return database.query(DatabaseHelper.TABLE_EVENTS, projection, selection, selectionArgs, null, null, sortOrder);default:throw new IllegalArgumentException("Unknown URI: " + uri);}}@Nullable@Overridepublic Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {long id = database.insert(DatabaseHelper.TABLE_EVENTS, null, values);getContext().getContentResolver().notifyChange(uri, null);return ContentUris.withAppendedId(CONTENT_URI, id);}@Overridepublic int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {introwsDeleted;switch (uriMatcher.match(uri)) {case EVENTS:rowsDeleted = database.delete(DatabaseHelper.TABLE_EVENTS, selection, selectionArgs);break;case EVENT_ID:selection = DatabaseHelper.COLUMN_ID + "=?";selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};rowsDeleted = database.delete(DatabaseHelper.TABLE_EVENTS, selection, selectionArgs);break;default:throw new IllegalArgumentException("Unknown URI: " + uri);}getContext().getContentResolver().notifyChange(uri, null);return rowsDeleted;}@Overridepublic int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {int rowsUpdated;switch (uriMatcher.match(uri)) {case EVENTS:rowsUpdated = database.update(DatabaseHelper.TABLE_EVENTS, values, selection, selectionArgs);break;case EVENT_ID:selection = DatabaseHelper.COLUMN_ID + "=?";selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};rowsUpdated = database.update(DatabaseHelper.TABLE_EVENTS, values, selection, selectionArgs);break;default:throw new IllegalArgumentException("Unknown URI: " + uri);}getContext().getContentResolver().notifyChange(uri, null);return rowsUpdated;}@Nullable@Overridepublic String getType(@NonNull Uri uri) {switch (uriMatcher.match(uri)) {case EVENTS:return "vnd.android.cursor.dir/vnd.com.example.calendarprovider.events";case EVENT_ID:return "vnd.android.cursor.item/vnd.com.example.calendarprovider.event";default:throw new IllegalArgumentException("Unknown URI: " + uri);}}
}

3. 总结

ContentProvider 是 Android 中用于数据共享和管理的核心机制,特别适用于跨进程数据访问。在开发中,通过合理设计和优化,可以充分利用 ContentProvider 的优势,实现高效的数据操作。实践中,通过批量操作、异步任务、缓存机制等手段,可以显著提升 ContentProvider 的性能,确保应用的稳定性和用户体验。结合实际场景,选择合适的优化技巧和设计模式,是开发高性能 Android 应用的关键。

欢迎点赞|关注|收藏|评论,您的肯定是我创作的动力

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/51312.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

本周热点丨快手《可灵》国际版正式上线、《王者荣耀》国际服海外下载量破5000万

7月第4周 秦彻带动《恋与深空》2.0霸榜全球 《蔚蓝档案》上线3.5周年庆典版本,登顶日服iOS畅销榜 《Honor of Kings》下载量突破五千万 英伟达将开发"Blackwell"的中国定制版芯片 人工智能初创公司Cohere获得5亿美元融资 Fal AI推出全新开源图像生成模型A…

reshape函数及MATLAB应用

reshape 函数在 MATLAB 中是一个非常有用的函数,通过重新排列现有元素来重构数组。它允许你重新调整数组(或矩阵)的尺寸,而不改变其数据。这个函数特别适用于当你需要将一个矩阵或数组从一种结构转换为另一种结构时,只…

Python 入门学习第三课

# 遍历列表 # 通常使用for循环 格式 for 自己定义的名字:列表: # 冒号不要忘记了 在这之后 需要缩进 如果不缩进 将进行一次 message [zahngsan,lisi,wangwu] for wq in message:print(wq) # 练习题 message [xiande,tiande,choude] for wq in message:print(wq) …

【GoodERP更新日志】发票管理 模块 增加 批量通知开票 功能结算单 增加 按凭证号查询、按是否生成凭证 查询 筛选

开源项目GoodERP更新-2024年7月28日 本次提交合并增加的功能或解决的问题: 1、结算单 增加 按凭证号查询、按是否生成凭证 查询 筛选 2、增加发票 批量通知开票 功能 3、修正发票号码为8或20位校验 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来…

AFSim 仿真系统--任务处理器入门指南

任务处理器 任务处理器(WSF_TASK_PROCESSOR)是一个WSF处理器,它提供了检查轨迹管理器中的数据(轨迹)并对其采取行动的能力。这些行动包括: *向下属分配任务 *激活或停用传感器或干扰器 *开火武器 *操纵平台…

Vue项目发布后浏览器缓存问题解决

1. 现象描述 每次Jenkins自动化发布Vue项目后&#xff0c;用户需要手动全部清理历史缓存数据才可以使用系统&#xff0c;用户体验非常不好 2. 解决方案 2.1 配置public/index.html 配置index.html, 在首页启动no-store禁止缓存 <meta http-equiv"pragram" co…

达梦数据库系列—35.DM常用SQL

目录 实例相关 用户权限 内存相关 表相关 分区表/索引 表空间 文件相关 数据文件 undo文件 Temp文件 在线日志 归档日志 备份还原 JOB相关 主备 DSC ASM 会话相关 锁相关 sql相关 执行计划 系统负载 实例相关 版本 select * from v$version; select id…

昇思MindSpore 应用学习-DCGAN生成漫画头像-CSDN

日期 心得 昇思MindSpore 应用学习-DCGAN生成漫画头像&#xff08;AI代码学习&#xff09; DCGAN生成漫画头像 在下面的教程中&#xff0c;我们将通过示例代码说明DCGAN网络如何设置网络、优化器、如何计算损失函数以及如何初始化模型权重。在本教程中&#xff0c;使用的动…

vue2和el-input无法修改和写入,并且不报错

文章目录 一. 业务场景描述二. 原因分析三.解决方案3.1 方案一 原生标签&#xff08;不建议&#xff09;3.2 方案二 父子传递&#xff08;不建议&#xff09;3.3 方案三 vuex&#xff0c;pinia 状态传值&#xff08;不建议&#xff09;3.4 方案四 vue初始化属性 &#xff08;建…

Java从入门到精通(十三)~ 枚举和注解

晚上好&#xff0c;愿这深深的夜色给你带来安宁&#xff0c;让温馨的夜晚抚平你一天的疲惫&#xff0c;美好的梦想在这个寂静的夜晚悄悄成长。 文章目录 目录 前言 一、枚举 1.1 枚举的概念 ​编辑 1.2 枚举的特点 1.3 枚举的实际运用 1. 状态机&#xff0c;描述属性的…

Nginx配置详解

1. Nginx安装 进入到/usr/local目录下&#xff0c;执行命令&#xff1a; yum install -y nginx通过如下命令启动nginx服务 systemctl start nginx通过如下命令&#xff0c;设置nginx开启自启动 systemctl enable nginxnginx默认占用80端口。 访问ip:80&#xff0c;可以看到…

Open3D 点云按xyz轴等距切片

目录 一、概述 1.1原理 1.2实现步骤 1.3应用 二、代码实现 2.1关键函数 2.2完整代码 三、实现效果 3.1原始点云 3.2按x轴切片 3.3按y轴切片 3.4按z轴切片 Open3D点云算法汇总及实战案例汇总的目录地址&#xff1a; Open3D点云算法与点云深度学习案例汇总&#xff…

Java中线程池的基本使用

参考这个课程&#xff0c;讲的非常详细 27.线程池使用步骤总结_哔哩哔哩_bilibili 应用场景 商品秒杀 文件上传 订票系统 自定义线程池&#xff08;让我们了解底层逻辑的&#xff09; 构造方法 饱和机制 就是我们的队列饱和后我们该怎么处理 是拒绝这个任务还是啥…

Aria2 任意文件写入漏洞

目录 Aria2介绍漏洞描述漏洞复现 Aria2介绍 Aria2是一个在命令行下运行&#xff0c;多协议&#xff0c;多来源下载工具&#xff08;HTTP / HTTPS&#xff0c;FTP&#xff0c;BitTorrent&#xff0c;Metalink&#xff09;&#xff0c;内建XML-RPC用户界面。Aria提供RPC服务器&a…

流媒体服务器一:使用成熟的流媒体SRS 搭建 RTMP流媒体服务器

1 安装和测试srs流媒体服务器 服务器&#xff1a;SRS(Simple RTMP Server&#xff0c;⽀持RTMP、HTTP-FLV&#xff0c;HLS) 推流端&#xff1a;ffmpeg OBS 拉流端&#xff1a;ffplay VLC srs播放器 1.1 安装srs流媒体服务器 官网 SRS (Simple Realtime Server) | SRS 码…

18746 逆序数

这个问题可以使用归并排序的思想来解决。在归并排序的过程中&#xff0c;我们可以统计逆序数的数量。当我们合并两个已经排序的数组时&#xff0c;如果左边的数组中的元素&#xfffd;&#xfffd;于右边的数组中的元素&#xff0c;那么就存在逆序&#xff0c;逆序数的数量就是…

数据库之索引

目录 一、索引概述 1.索引的概念和特点 2.索引的分类 3.索引设计的原则 二、创建和查看索引 1.在创建表的时候创建索引 1.创建和查看普通索引 2.创建组合索引 3.创建唯一索引 4.创建全文索引 5.创建空间索引 2.在已有的表上创建索引 1.使用ALTER TABLE语句创建索引…

IEC104转MQTT网关支持MQTT对接Ignition、阿里云、华为云、亚马逊AWS、ThingsBoard、Zabbix平台助力远程管理

钡铼推出了一款专为电力系统设计的数据采集网关——IEC104转MQTT网关BE113&#xff0c;感兴趣的朋友接着往下看&#xff1a; 一、网关概述 IEC104转MQTT(Ignition)网关BE113是一款专为电力系统设计的数据采集网关&#xff0c;支持DL/T645和IEC104等协议的设备。上行支持MQTT协…

二、3 函数递归

自己间接或直接调用自己&#xff08;可大大减少代码量&#xff09; 1、举例 2、递归必须有停下来的条件 3、举例 普通求解数组长度 递归求解

16 敏捷开发实践(1)

敏捷方法&#xff1a;是一种从1990年代开始逐渐引起广泛关注的一些新型软件开发方法&#xff0c;是一种应对快速变化的需求的一种软件开发能力。 敏捷开发&#xff1a;是一种以人为核心、迭代、循序渐进的开发方法。 敏捷实践&#xff1a;精益软件开发&#xff08;LSD&#x…