深入分析 Android ContentProvider (九)

news2024/9/17 7:48:05

文章目录

    • 深入分析 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
    @Override
    public 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
    @Override
    public String getType(@NonNull Uri uri) {
        return "image/jpeg"; // 根据文件类型返回 MIME 类型
    }

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        // 插入逻辑
        return null;
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
        // 删除逻辑
        return 0;
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
        // 更新逻辑
        return 0;
    }

    @Nullable
    @Override
    public 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.coloradmin.cn/o/1959280.html

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

相关文章

jmeter录制

1、添加代理服务器 添加方法:“测试计划”右键 -> 添加 -> 非测试元件 -> HTTP代理服务器 2、添加线程组 添加方法:“测试计划”右键->添加->线程(用户)->线程组 3、配置http代理服务器 (1&a…

电脑录屏软件带声音,3款软件推荐,一键录制

在今天,电脑录屏软件带声音的功能已经悄然改变了我们的学习、工作和娱乐方式。录屏软件,这个看似简单的工具,实则蕴藏着无穷的魅力。它不仅能够捕捉屏幕上的每一个细节,还能将声音完美地融入其中。无论是游戏中的背景音乐、会议中…

谷粒商城实战笔记-77-商品服务-API-平台属性-规格参数列表

文章目录 一,新增product/attr/base/list接口二,踩坑记录1. 使用 Lazy 注解2. 使用 PostConstruct 注解代码分析解决方案分析 这一节的主要内容是完成规格参数的列表查询功能。 一,新增product/attr/base/list接口 这个接口用来查询规格参数…

电力巡检红外热成像夜视手持终端有多强?

电力巡检红外热成像夜视手持终端在电力巡检中展现出强大的功能和应用价值。这些手持终端结合了红外热成像技术和夜视功能,能够在夜间或光线不足的环境下对电力设备进行精确的温度测量和状态监测。以下是对其强大之处的详细分析: 1. 精准的红外热成像能力…

【机器学习】正规方程的简单介绍以及如何使用Scikit-Learn实现基于正规方程的闭式解线性回归

引言 Scikit-learn 是一个开源的机器学习库,它支持 Python 编程语言。它提供了多种机器学习算法的实现,并用于数据挖掘和数据分析 文章目录 引言一、正规方程的定义二、正规方程的原理三、使用 Scikit-Learn 实现基于正规方程的闭式解线性回归3.1 工具3.…

爬虫“拥抱大模型”,有没有搞头?

验证码坐标识别 数据采集过程中,可能会碰到各种风控策略。其中,验证码人机验证是较为常见的,点选类验证码需要识别出相应的坐标,碰到这种情况,一般要么自己训练模型,要么对接打码平台。现在也可以将识别工…

RocketMQ事务消息机制原理

RocketMQ工作流程 在RocketMQ当中,当消息的生产者将消息生产完成之后,并不会直接将生产好的消息直接投递给消费者,而是先将消息投递个中间的服务,通过这个服务来协调RocketMQ中生产者与消费者之间的消费速度。 那么生产者是如何…

领夹麦哪个牌子音质好?直播采访十大公认音质好的麦克风!

在追求内容品质的今天,音频质量成为了衡量作品成功与否的关键指标之一。对于频繁出镜的互联网从业者、短视频创作者及直播达人而言,一款性能卓越的无线领夹麦克风无疑是提升专业形象的得力助手。它不仅轻便易携,更能在复杂环境中捕捉纯净、清…

[QT开发_音乐播放器项目笔记01]

目录 一:常用类 26 QByteArray 是 Qt 框架中的一个类,用于处理字节数组。它提供了动态大小的字节数组,可以用于存储和操作二进制数据,比如文件内容、网络数据等。 QT项目记录: 一:常用类 26 QByteArray…

capl代码写法

CAPL是一种专门用于构建通信系统测试脚本的编程语言,全称为"Communication Access Programming.Language"。 CAPL是一种类C语言的解释性脚本语言,常用于CAN和LIN总线等通信系统的开发和测试中。 CAPL提供了丰富的库函数和API,可以用…

【Spring Cloud】Sleuth +Zinkin 实现链路追踪并持久化的解决方案

文章目录 前言链路追踪介绍Sleuth入门Sleuth介绍TraceSpanAnnotation Sleuth入门1、引入依赖2、修改配置文件3、网关路由配置4、演示 Zipkin的集成ZipKin介绍ZipKin服务端安装Zipkin客户端集成1、添加依赖2、添加配置3、访问微服务4、演示 Zipkin数据持久化使用mysql实现数据持…

vue3.0学习--创建项目,基于vite创建

vite 官网地址:https://cn.vitejs.dev/guide/ 1,执行创建命令 npm create vitelatest 2, cd my3d ---- my3d 是创建的项目名字 3,npm install ---- 安装需要的插件包 4,npm run format ---- 通常用于代码格式化 5, npm…

【Docker】Docker 的背景

一、容器技术发展史 1、Jail 时代 容器不是一个新概念或者新技术,很早就有了,只是近几年遇到了云计算,整个技术被彻底引爆了。 (1)1979 年贝尔实验室发明 chroot chroot 系统调用是在 1979 年开发第 7 版 Unix 期间…

Java多重循环控制,break,continue,return

目录 1.多重循环控制 执行步骤分析 案例演示 2.跳转控制语句-break 基本介绍 基本语法 示意图 注意事项和细节说明 练习题 3.跳转控制语句-continue 基本介绍 基本语法 示意图 细节案例分析和说明 4.跳转控制语句-return 介绍 1.多重循环控制 执行步骤分析…

django基于大数据的电影推荐系统-计算机毕业设计源码71246

目 录 摘 要 1 绪论 1.1 选题背景与意义 1.2研究现状 1.3研究内容 1.4 开发环境 1.5论文结构与章节安排 2 相关理论和技术 2.1 协同过滤算法 2.2 B/S体系结构介绍 2.3 Python爬虫技术 2.4 Django框架介绍 2.5 MySQL数据库 3 电影推荐系统系统分析 3.1 可行性分析…

微信小程序审核的一些总结记录

1、文字ocr识别工具,识别ocr文字,显示出文字 这么简单的东西,说是“涉及提供图片/音频/制作、剪辑服务”,这个工具代码也就下图几行,这是哪门子的图片编辑,别管它,直接重新提交审核。 2、个人不…

营销人看巴黎奥运会,看到了什么?

不同的人眼中的巴黎奥运会是不一样的:环保人士关注奥运场馆的绿色设计,以及赛事期间对可再生能源的利用;旅游博主用镜头捕捉巴黎奥运会每一个精彩瞬间;社会学家在巴黎奥运会看到多元文化的交流与融合…… 那么营销人在巴黎奥运会…

基于IDEA+MySQL+Springboot开发的医药进销存系统

基于IDEAMySQLSpringboot开发的医药进销存系统 项目介绍💁🏻 1.创建数据库tedu_DIEMS,并导入数据库文件 2.导入项目,import-maven 3.修改application.properties的数据库IP地址、用户名和密码,改为自己的信息 4.找到Di…

嵌入式学习第11天——C语言选择结构

2024年7月29日 第11天 选择&#xff08;分支&#xff09;结构 分支结构&#xff1a;又被称为选择结构 概念 选择结构&#xff1a;根据条件成立与否&#xff0c;选择相应的操作。 条件构建 关系表达式&#xff1a;含有关系运算符的表达式&#xff08;>,<,>,<,!…

Oracle大师Roger Cornejo的推荐:使用ASH诊断Oracle解析故障

这篇文章被Oracle大师Roger Cornejo在X平台上推荐&#xff08;见下图&#xff09;&#xff0c;英文原文在&#xff1a; Diagnosing Parsing Issue with ASH 解析&#xff0c;尤其是硬解析&#xff0c;是非生产性操作&#xff0c;会消耗大量系统资源&#xff0c;导致库缓存争用…