深入分析 Android ContentProvider (九)

文章目录

    • 深入分析 Android ContentProvider (九)
    • ContentProvider 的高级使用及最佳实践(续)
      • 1. 复杂查询与联合查询
        • 复杂查询示例
      • 2. 数据同步与一致性
        • 示例:使用事务确保数据一致性
      • 3. 数据分页加载
        • 示例:分页加载数据
      • 4. 内容提供者中的多媒体文件处理
        • 示例:处理多媒体文件的 ContentProvider
      • 5. 常见陷阱与解决方案
        • 5.1. 数据库锁定
        • 5.2. 权限管理
        • 5.3. 内存泄漏
          • 示例:避免内存泄漏
      • 6. 总结

深入分析 Android ContentProvider (九)

ContentProvider 的高级使用及最佳实践(续)

1. 复杂查询与联合查询

在实际应用中,可能会遇到需要执行复杂查询或联合查询的情况。ContentProvider 提供了多种方式来支持这些操作。

复杂查询示例

假设我们在音乐播放器应用中需要查询某个播放列表中的所有歌曲,并且需要按特定条件进行筛选和排序。

@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,@Nullable String[] selectionArgs, @Nullable String sortOrder) {SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();switch (uriMatcher.match(uri)) {case PLAYLISTS:queryBuilder.setTables(DatabaseHelper.TABLE_PLAYLIST);break;case PLAYLIST_ID:queryBuilder.setTables(DatabaseHelper.TABLE_PLAYLIST);queryBuilder.appendWhere(DatabaseHelper.COLUMN_ID + "=" + uri.getLastPathSegment());break;case PLAYLIST_SONGS:queryBuilder.setTables(DatabaseHelper.TABLE_PLAYLIST + " JOIN " + DatabaseHelper.TABLE_SONG +" ON " + DatabaseHelper.TABLE_PLAYLIST + "." + DatabaseHelper.COLUMN_ID + "=" +DatabaseHelper.TABLE_SONG + "." + DatabaseHelper.COLUMN_PLAYLIST_ID);break;default:throw new IllegalArgumentException("Unknown URI: " + uri);}Cursor cursor = queryBuilder.query(database, projection, selection, selectionArgs, null, null, sortOrder);cursor.setNotificationUri(getContext().getContentResolver(), uri);return cursor;
}

在这个示例中,SQLiteQueryBuilder 被用来构建查询语句。通过 setTables 方法,我们可以指定查询的表,并且可以通过 appendWhere 方法添加查询条件。此外,通过联合查询,可以从多个表中获取数据。

2. 数据同步与一致性

确保数据的一致性和同步是 ContentProvider 使用中的一个重要方面。在多线程环境中,使用事务和同步机制来确保数据的一致性和完整性非常重要。

示例:使用事务确保数据一致性
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {SQLiteDatabase db = dbHelper.getWritableDatabase();long id;db.beginTransaction();try {id = db.insertOrThrow(DatabaseHelper.TABLE_PLAYLIST, null, values);db.setTransactionSuccessful();} finally {db.endTransaction();}getContext().getContentResolver().notifyChange(uri, null);return ContentUris.withAppendedId(CONTENT_URI, id);
}

通过使用事务,我们可以确保插入操作的原子性,即要么所有操作成功执行,要么所有操作都回滚。

3. 数据分页加载

在处理大数据集时,分页加载数据可以显著提升性能和用户体验。分页加载可以减少内存使用和响应时间。

示例:分页加载数据
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,@Nullable String[] selectionArgs, @Nullable String sortOrder) {int limit = 50;int offset = 0;if (uri.getQueryParameter("limit") != null) {limit = Integer.parseInt(uri.getQueryParameter("limit"));}if (uri.getQueryParameter("offset") != null) {offset = Integer.parseInt(uri.getQueryParameter("offset"));}String limitClause = offset + "," + limit;SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();queryBuilder.setTables(DatabaseHelper.TABLE_PLAYLIST);Cursor cursor = queryBuilder.query(database, projection, selection, selectionArgs, null, null, sortOrder, limitClause);cursor.setNotificationUri(getContext().getContentResolver(), uri);return cursor;
}

通过添加 limitoffset 参数,可以实现分页加载。用户可以在 URI 中指定这两个参数来控制每次查询的数据量。

4. 内容提供者中的多媒体文件处理

在多媒体应用中,ContentProvider 可以用来管理和提供多媒体文件(如图片、视频和音频)。ContentProvider 可以提供对文件的 URI 访问,允许其他应用通过 URI 访问这些文件。

示例:处理多媒体文件的 ContentProvider
public class MediaContentProvider extends ContentProvider {private static final String AUTHORITY = "com.example.mediaprovider";private static final String BASE_PATH = "media";public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH);@Nullable@Overridepublic Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,@Nullable String[] selectionArgs, @Nullable String sortOrder) {File file = new File(getContext().getFilesDir(), uri.getLastPathSegment());MatrixCursor cursor = new MatrixCursor(new String[]{"_id", "_data"});cursor.addRow(new Object[]{0, file.getAbsolutePath()});return cursor;}@Nullable@Overridepublic String getType(@NonNull Uri uri) {return "image/jpeg"; // 根据文件类型返回 MIME 类型}@Nullable@Overridepublic Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {// 插入逻辑return null;}@Overridepublic int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {// 删除逻辑return 0;}@Overridepublic int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {// 更新逻辑return 0;}@Nullable@Overridepublic ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException {File file = new File(getContext().getFilesDir(), uri.getLastPathSegment());return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);}
}

在这个示例中,openFile 方法返回一个 ParcelFileDescriptor,允许其他应用通过 URI 访问文件。这种方法对于共享多媒体文件特别有用。

5. 常见陷阱与解决方案

5.1. 数据库锁定

长时间的数据库操作可能导致数据库锁定,影响应用性能。解决方案是使用批量操作和异步处理。

5.2. 权限管理

滥用权限可能导致安全问题。确保只授予必要的权限,并在代码中严格检查权限。

5.3. 内存泄漏

未正确关闭 Cursor 或其他资源可能导致内存泄漏。确保在使用完 Cursor 后及时关闭它们。

示例:避免内存泄漏
Cursor cursor = null;
try {cursor = getContext().getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);if (cursor != null && cursor.moveToFirst()) {// 处理数据}
} finally {if (cursor != null) {cursor.close();}
}

6. 总结

ContentProvider 是 Android 应用中强大的数据管理和共享机制,通过深入理解和灵活运用,可以实现高效、安全的数据操作。在实际开发中,结合具体需求和场景,合理设计 URI 结构、权限管理、数据缓存和分页加载等高级技巧,是开发高性能、稳定 Android 应用的关键。理解和掌握 ContentProvider 的高级使用方法,可以让开发者在数据管理和共享方面得心应手。通过具体的代码示例和实践案例,我们展示了 ContentProvider 的广泛应用和最佳实践。

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

在这里插入图片描述

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

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

相关文章

【CN】Argo 持续集成和交付(二)

7.25.通知 概述 Argo CD 通知持续监控 Argo CD 应用程序,并提供一种灵活的方式来通知用户应用程序状态的重要变化。使用灵活的触发器和模板机制,可以配置何时发送通知以及通知内容。Argo CD 通知包含有用的触发器和模板目录。因此,可以直接…

pycharm连接mysql

1、按照下图在pycharm找到数据库设置 在PyCharm右侧工具栏有Database,点击打开如果没有,则在view | Tool Windows | Database 选择显示 2、按照下图所示位置找到mysql(本机由于配置过,所以由recent,第一次配置在列表中…

Cybersecurity ASPICE实施策略-基于ISO/SAE 21434-亚远景科技

近几年,随着软件定义汽车和汽车的智能化和网联化,使得汽车融合了现代通信与网络通信技术,实现了车与人、车与车、车与道路、车与云端等智能信息交互和共享,也让车具备了环境感知、协同控制、智能决策等功能;与此同时&a…

苹果推送iOS 18.1带来Apple Intelligence预览

🦉 AI新闻 🚀 苹果推送iOS 18.1带来Apple Intelligence预览 摘要:苹果向iPhone和iPad用户推送iOS 18.1和iPadOS 18.1开发者预览版Beta更新,带来“Apple Intelligence”预览。目前仅支持M1芯片或更高版本的设备。Apple Intellige…

使用 Elasticsearch 和 LlamaIndex 保护 RAG 中的敏感信息和 PII 信息

作者:来自 Elastic Srikanth Manvi 在这篇文章中,我们将研究在 RAG(检索增强生成)流程中使用公共 LLMs 时保护个人身份信息 (personal identifiable information - PII) 和敏感数据的方法。我们将探索使用开源库和正则表达式屏蔽 …

正余弦算法作者又提出新算法!徒步优化算法(HOA)-2024年一区顶刊新算法-公式原理详解与性能测评 Matlab代码免费获取

声明:文章是从本人公众号中复制而来,因此,想最新最快了解各类智能优化算法及其改进的朋友,可关注我的公众号:强盛机器学习,不定期会有很多免费代码分享~ 目录 原理简介 算法伪代码 性能测评 参考文献 …

基于vue-onlyoffice实现企业office web在线应用

目录 1.背景... 1 2.Onlyoffice介绍... 2 3.Onlyoffice核心api介绍... 2 3.1 ApiDocument 2 3.2 ApiParagraph. 2 3.3 ApiTable. 2 3.4. ApiRange. 3 4.Onlyoffice插件介绍... 3 4.1 插件定义... 3 4.2 插件对象... 3 4.3 插件结构... 4 4.4 插件内嵌使用方式... 4…

搜索引擎项目(四)

SearchEngine 王宇璇/submit - 码云 - 开源中国 (gitee.com) 基于Servlet完成前后端交互 WebServlet("/searcher") public class DocSearcherServlet extends HttpServlet {private static DocSearcher docSearcher new DocSearcher();private ObjectMapper obje…

Luma AI发布文生视频大模型Dream Machine——可免费在线试玩

Sora模型的文生视频能力,想必一定惊艳过你。虽然Sora模型很惊艳,但是并没有开放给普通大众。Luma AI发布文生视频大模型Dream Machine模型,可以免费供大家使用,任何人只要到Luma AI的官方网站,就可体验Luma AI的文生视…

六个开源的PDF转Markdown项目

✨ 1: gptpdf gptpdf 是一个利用VLLM解析PDF为Markdown的工具,几乎完美支持数学公式、表格等。 GPTPDF 是一个使用视觉大模型(如 GPT-4o)将 PDF 文件解析成 Markdown 文件的工具。它主要用于高效地解析 PDF 文档中的排版、数学公式、表格、…

React Native新架构系列-新架构介绍

从今天起,会陆续更新React Native新架构相关的系列内容,本系列基于React Native 0.73.4版本,从一名Android开发者的视角进行介绍。本系列介绍的内容默认读者对React Native有一定的了解,对基础的开发内容不再赘述。 前言 首先介绍…

【优选算法】——leetcode——438.找到字符串中所有字母异位词

目录 1.题目 2.题目理解 3.算法原理 1.如何快速判断两个字符串是否是异位词 2.解决问题 暴力求解——>滑动窗口哈希表 滑动窗口 利用滑动窗口哈希表解决问题 优化:更新结果的判断条件 4.编程代码 C代码 1.频率统计 2. 双指针 C语言代码 1.字符频率…

【qt小系统】传感器云平台3D散点图(附源码)

摘要:本文主要使用QT5,实现了一个传感器云平台的小示例,模拟的是各类传感器的添加,例如:热成像传感器、温度传感器、超声波传感器,模拟添加完成后,会自动将此传感器的三维坐标增加到3D散点图上&…

Vmware安装openstack

安装虚拟机 创建完成后,点击开启虚拟机 稍等执行成功后 上传压缩包到指定目录。将yoga_patch.tar.gz包上传至/root目录下,将stack3_without_data.tar.gz包使用WinSCP上传至/opt目录下 vim run_yoga.sh #/bin/bash cd /root sudo apt-get update tar -xzv…

「问题解决」jdk高版本导致请求返回对象转换报错

报错:Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected native java.lang.Object java.lang.Object.clone() throws java.lang.CloneNotSupportedException accessible: module java.base does not “opens java.lang” to unn…

UnityShaderUI编辑器扩展

前言: 当我们在制作通用Shader的时候,避免不了许多参数混杂在一起,尽管在材质面板已经使用过Header标签来区分,但是较长的Shader参数就会导致冗余,功能块不够简约明了,如图: 对于Shader制作者来…

FPGA开发——蜂鸣器的控制

一、概述 在项目开发的过程当中,我会通常会需要一个东西就行报警显示,有使用语音报警,信息报警等注入此类的方式,但最为简单使用的还是蜂鸣器的使用,蜂鸣器控制简单,成本低,是最为常用的模块之…

NSSRound#4 Team

[NSSRound#4 SWPU]1zweb 考察&#xff1a;phar的反序列化 1.打开环境&#xff0c;审计代码 1.非预期解 直接用file伪协议读取flag,或直接读取flag file:///flag /flag 2.正常解法 用读取文件读取index.php,upload.php的源码 index.php: <?php class LoveNss{publi…

环境搭建-Docker搭建ClickHouse

Docker搭建ClickHouse 一、前言二、ClickHouse安装2.1 拉取镜像运行ClickHouse服务 三、测试安装3.1 进入clickhouse容器3.2 命令补充说明 四、测试连接五、设置CK的用户名密码 一、前言 本文使用的Docker使用Windows搭建&#xff0c;Linux版本的搭建方式一样。 Windows系统搭…

Data Race: 并发编程中的数据竞争问题

Data Race: 并发编程中的数据竞争问题 &#x1f50d; &#x1f680; Data Race: 并发编程中的数据竞争问题 &#x1f50d;摘要引言正文内容一、什么是数据竞争&#xff1f; &#x1f914;1.1 数据竞争的定义1.2 数据竞争的特征 二、数据竞争的原因和影响 &#x1f6a8;2.1 原因…