当前位置: 首页 > news >正文

深入分析 Android ContentProvider (三)

文章目录

    • 深入分析 Android ContentProvider (三)
    • ContentProvider 的高级使用和性能优化
      • 1. 高级使用场景
        • 1.1. 数据分页加载
          • 示例:分页加载
        • 1.2. 使用 Loader 实现异步加载
          • 示例:使用 CursorLoader 加载数据
        • 1.3. ContentProvider 与权限管理
          • 示例:配置权限
      • 2. 性能优化策略
        • 2.1. 缓存机制
          • 示例:使用 LruCache 进行缓存
        • 2.2. 批量操作
          • 示例:批量插入数据
        • 2.3. 使用异步操作
          • 示例:使用 AsyncTask 进行异步查询
        • 2.4. 索引优化
          • 示例:创建索引
      • 3. 总结

深入分析 Android ContentProvider (三)

ContentProvider 的高级使用和性能优化

在实际应用中,合理使用 ContentProvider 并进行性能优化是确保应用高效运行的关键。以下内容将介绍一些高级使用场景和性能优化策略。

1. 高级使用场景

1.1. 数据分页加载

对于大量数据的查询,可以通过分页加载提高效率。分页加载常用于列表视图中,以避免一次性加载所有数据导致的性能问题。

示例:分页加载

query 方法中实现分页加载:

@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,@Nullable String[] selectionArgs, @Nullable String sortOrder) {int limit = 20; // 每页加载的数据量int offset = 0; // 偏移量String limitClause = " LIMIT " + limit + " OFFSET " + offset;Cursor cursor;switch (uriMatcher.match(uri)) {case EXAMPLES:cursor = database.query(DatabaseHelper.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder + limitClause);break;case EXAMPLE_ID:cursor = database.query(DatabaseHelper.TABLE_NAME, projection, DatabaseHelper.COLUMN_ID + "=?",new String[]{String.valueOf(ContentUris.parseId(uri))}, null, null, sortOrder);break;default:throw new IllegalArgumentException("Unknown URI: " + uri);}cursor.setNotificationUri(getContext().getContentResolver(), uri);return cursor;
}

在调用端实现分页查询:

Uri uri = Uri.parse("content://com.example.provider/example");
String sortOrder = "name ASC LIMIT 20 OFFSET 0"; // 加载第一页数据
Cursor cursor = getContentResolver().query(uri, null, null, null, sortOrder);
if (cursor != null) {while (cursor.moveToNext()) {String name = cursor.getString(cursor.getColumnIndexOrThrow("name"));// 处理数据}cursor.close();
}
1.2. 使用 Loader 实现异步加载

使用 Loader 可以在异步线程中加载数据,避免在主线程中进行耗时操作,从而保持 UI 的流畅性。CursorLoader 是一个常用的 Loader,用于 ContentProvider 的异步查询。

示例:使用 CursorLoader 加载数据

实现一个 LoaderManager.LoaderCallbacks<Cursor> 接口:

public class ExampleActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor> {private static final int LOADER_ID = 1;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_example);getSupportLoaderManager().initLoader(LOADER_ID, null, this);}@NonNull@Overridepublic Loader<Cursor> onCreateLoader(int id, @Nullable Bundle args) {Uri uri = Uri.parse("content://com.example.provider/example");return new CursorLoader(this, uri, null, null, null, "name ASC");}@Overridepublic void onLoadFinished(@NonNull Loader<Cursor> loader, Cursor data) {// 处理加载完成的数据}@Overridepublic void onLoaderReset(@NonNull Loader<Cursor> loader) {// 清理资源}
}
1.3. ContentProvider 与权限管理

在一些安全性要求较高的场景下,合理配置 ContentProvider 的权限是非常重要的。通过权限声明和 URI 权限授予,可以确保数据访问的安全性。

示例:配置权限

AndroidManifest.xml 中声明权限,并为 ContentProvider 设置权限:

<permission android:name="com.example.provider.READ" android:protectionLevel="signature" />
<permission android:name="com.example.provider.WRITE" android:protectionLevel="signature" />
<providerandroid:name=".ExampleProvider"android:authorities="com.example.provider"android:exported="true"android:readPermission="com.example.provider.READ"android:writePermission="com.example.provider.WRITE" />

在代码中授予 URI 权限:

getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

2. 性能优化策略

2.1. 缓存机制

通过缓存机制,可以减少对数据库的频繁访问,提高数据查询的效率。可以使用内存缓存或磁盘缓存来存储常用数据。

示例:使用 LruCache 进行缓存
private LruCache<String, Bitmap> mMemoryCache;public void initCache() {final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);final int cacheSize = maxMemory / 8;mMemoryCache = new LruCache<>(cacheSize);
}public void addBitmapToMemoryCache(String key, Bitmap bitmap) {if (getBitmapFromMemCache(key) == null) {mMemoryCache.put(key, bitmap);}
}public Bitmap getBitmapFromMemCache(String key) {return mMemoryCache.get(key);
}
2.2. 批量操作

在对数据进行插入、更新或删除时,使用批量操作可以减少数据库的锁定次数,提高操作效率。

示例:批量插入数据
ArrayList<ContentProviderOperation> operations = new ArrayList<>();
for (int i = 0; i < 100; i++) {ContentValues values = new ContentValues();values.put("name", "Example " + i);operations.add(ContentProviderOperation.newInsert(CONTENT_URI).withValues(values).build());
}
try {getContentResolver().applyBatch("com.example.provider", operations);
} catch (RemoteException | OperationApplicationException e) {e.printStackTrace();
}
2.3. 使用异步操作

避免在主线程中进行数据库操作,使用 AsyncTaskLoaderRxJava 等异步框架进行数据操作,确保 UI 的流畅性。

示例:使用 AsyncTask 进行异步查询
private class QueryTask extends AsyncTask<Void, Void, Cursor> {@Overrideprotected Cursor doInBackground(Void... voids) {Uri uri = Uri.parse("content://com.example.provider/example");return getContentResolver().query(uri, null, null, null, "name ASC");}@Overrideprotected void onPostExecute(Cursor cursor) {// 处理查询结果}
}
2.4. 索引优化

为频繁查询的字段创建索引,可以显著提高查询效率。可以在创建表时添加索引,或者在表创建后使用 SQL 语句添加索引。

示例:创建索引
private static final String TABLE_CREATE ="CREATE TABLE " + TABLE_NAME + " (" +COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +COLUMN_NAME + " TEXT);";private static final String INDEX_CREATE ="CREATE INDEX index_name ON " + TABLE_NAME + " (" + COLUMN_NAME + ");";@Override
public void onCreate(SQLiteDatabase db) {db.execSQL(TABLE_CREATE);db.execSQL(INDEX_CREATE);
}

3. 总结

通过上述高级使用场景和性能优化策略,可以更好地利用 ContentProvider 提供的数据共享和跨进程通信功能,构建高效、可靠的 Android 应用。在实际开发中,根据具体需求合理设计和优化 ContentProvider,可以大幅提升应用的性能和用户体验。

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

在这里插入图片描述

相关文章:

深入分析 Android ContentProvider (三)

文章目录 深入分析 Android ContentProvider (三)ContentProvider 的高级使用和性能优化1. 高级使用场景1.1. 数据分页加载示例&#xff1a;分页加载 1.2. 使用 Loader 实现异步加载示例&#xff1a;使用 CursorLoader 加载数据 1.3. ContentProvider 与权限管理示例&#xff1…...

养宠浮毛异味双困扰?性价比高的宠物空气净化器推荐

家里养了两只银渐层&#xff0c;谁懂啊&#xff01;一下班打开家门就看到家里飘满了猫浮毛雪&#xff0c;空气中还传来隐隐约约的异味。每天不是在吸毛的路上&#xff0c;就是在洗猫砂盆的路上&#xff0c;而且空气中的浮毛还很难清理干净&#xff0c;这是最让人头疼的问题。 …...

maven项目容器化运行之3-优雅的利用Jenkins和maven使用docker插件调用远程docker构建服务并在1Panel中运行

一.背景 在《maven项目容器化运行之1》中&#xff0c;我们开启了1Panel环境中docker构建服务给到了局域网。在《maven项目容器化运行之2》中&#xff0c;我们基本实现了maven工程创建、远程调用docker构建镜像、在1Panel选择镜像运行容器三大步骤。 但是&#xff0c;存在一个问…...

docker 打包orbbec

docker pull humble容器 sudo docker run -it osrf/ros:humble-desktop docker 启动容器 sudo docker run -u root --device/dev/bus/usb:/dev/bus/usb -it -v /home/wl:/share --name wl4 osrf/ros:humble-desktop /bin/bash新开一个终端 查看本地存在的容器&#xff1a;…...

无涯·问知财报解读,辅助更加明智的决策

财报解读就像是给公司做一次全面的体检&#xff0c;是理解公司内部运作机制和市场表现的一把钥匙&#xff0c;能够有效帮助投资者、分析师、管理层以及所有市场参与者判断一家公司的健康程度和发展潜力。 星环科技无涯问知的财经库内置了企业年报及财经类信息&#xff0c;并对…...

【Apache Doris】数据副本问题排查指南

【Apache Doris】数据副本问题排查指南 一、问题现象二、问题定位三、问题处理 本文主要分享Doris中数据副本异常的问题现象、问题定位以及如何处理此类问题。 一、问题现象 问题日志 查询报错 Failed to initialize storage reader, tablet{tablet_id}.xxx.xxx问题说明 查…...

【HarmonyOS】关于鸿蒙消息推送的心得体会(二)

【HarmonyOS】关于鸿蒙消息推送的心得体会&#xff08;二&#xff09; 前言 推送功能的开发与传统功能开发还是有很大区别。首先最大的区别点就在于需要多部门之间的协同&#xff0c;作为鸿蒙客户端开发&#xff0c;你需要和产品&#xff0c;运营&#xff0c;以及后台开发一起…...

零基础入门:创建一个简单的Python爬虫管理系统

摘要&#xff1a; 本文将手把手教你&#xff0c;从零开始构建一个简易的Python爬虫管理系统&#xff0c;无需编程基础&#xff0c;轻松掌握数据抓取技巧。通过实战演练&#xff0c;你将学会设置项目、编写基本爬虫代码、管理爬取任务与数据&#xff0c;为个人研究或企业需求奠…...

【Node.js基础04】node.js模块化

一&#xff1a;什么是模块化 在Node.js中&#xff0c;每个文件都可视为一个独立的模块。模块化提高了代码的复用性&#xff0c;按需加载&#xff0c;具有独立的作用域 二&#xff1a;如何实现多个文件间导入和导出 1 CommonJS标准&#xff08;默认&#xff09;-导入和导出 …...

数据库——单表查询

一、建立数据库mydb8_worker mysql> use mydb8_worker; 二、建立表 1.创建表 mysql> create table t_worker(department_id int(11) not null comment 部门号,-> worder_id int(11) primary key not null comment 职工号,-> worker_date date not null comment…...

dsa加训

refs: OI Wiki - OI Wiki (oi-wiki.org) 1. 枚举 POJ 2811 熄灯问题 refs : OpenJudge - 2811:熄灯问题 如果要枚举每个灯开或者不开的情况&#xff0c;总计2^30种情况&#xff0c;显然T。 不过我们可以发现&#xff1a;若第i行的某个灯亮了&#xff0c;那么有且仅有第i行和第…...

SpringBoot源码(1)ApplicationContext和BeanFactory

1、调用getBean方法 SpringBootApplication public class SpringBootDemoApplication {public static void main(String[] args) {ConfigurableApplicationContext applicationContext SpringApplication.run(SpringBootDemoApplication.class, args);applicationContext.get…...

CANoe编程实例--TCP/IP通信

1、简介 本实例将使用目前常用的开发工具C#来开发服务器端&#xff0c;以CANoe端作为客户端。服务器端和客户端&#xff0c;通过TCP/IP连接&#xff0c;实现数据交换。 首先在服务器端建立一个监听Socket&#xff0c;自动创建一个监听线程&#xff0c;随时监听是否有客户端的连…...

Neuron协议网关的北向应用插件开发

目录 概述 指令处理层开发​ 应用层开发​ .open​ .close​ .init​ .uninit​ .start​ .stop​ .setting​ .request​ 插件设置文件​ 适配华为的思路 概述 最近研究了一段时间的Neuron协议网关&#xff0c;前面的博文也提到它虽然能够把数据发到华为的IoT平台上…...

【BUG】已解决:You are using pip version 10.0.1, however version 21.3.1 is available.

You are using pip version 10.0.1, however version 21.3.1 is available. 目录 You are using pip version 10.0.1, however version 21.3.1 is available. 【常见模块错误】 【解决方案】 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#…...

electron-builder打包vue2项目不显示element-ui图标

1、使用版本 vue ^2.6.14element-ui ^2.15.14vue-cli-plugin-electron-builder 2.1.1 2、解决办法 1&#xff09; 如果是简单的图标可以使用图片代替&#xff08;这种对于elementui组件的图标还是不会显示&#xff09; 2&#xff09;在vue.config.js配置 const { defineCon…...

controller层-请求格式为json-请求方法为get

前置条件 get请求映射&#xff0c;内容和PostMapping一致&#xff0c;需要请求参数更换为get数据 请求过程&#xff1a;用户请求--初始化DispatcherServlet及对接和分发用户请求--controller--service 用户请求&#xff1a;http://ip:port/user/getinfo 请求方法&#xff1a;ge…...

【Linux】网络通信基础:应用层协议、HTTP、序列化与会话管理

文章目录 前言1. 应用层自定义协议与序列化1.1 什么是应用层&#xff1f;1.2 再谈 "协议"1.3 序列化 和 反序列化 2. HTTP 协议3. 认识 URL(统一资源定位符)4. urlencode和urldecode5. HTTP 协议请求与响应格式5.1 HTTP 请求5.2 HTTP 响应 6. HTTP 的方法6.1 GET 方法…...

@NotNull、@NotEmpty 和 @NotBlank 区别

NotNull、NotEmpty 和 NotBlank 是 Java Bean Validation (JSR 380) 规范中定义的注解&#xff0c;通常用于验证对象的属性是否满足特定的条件。这些注解常用于后端验证&#xff0c;确保接收到的数据符合预期。 NotNull 用途&#xff1a;验证一个对象是否不为null。 注意&#…...

大模型应用—大模型赋能网络爬虫

大模型赋能网络爬虫 简单来说,网页抓取就是从网站抓取数据和内容,然后将这些数据保存为XML、Excel或SQL格式。除了用于生成潜在客户、监控竞争对手和市场研究外,网页抓取工具还可以用于自动化你的数据收集过程。 借助AI网页抓取工具,可以解决手动或纯基于代码的抓取工具的…...

Ventoy终极指南:一个U盘启动所有系统,告别重复格式化烦恼 [特殊字符]

Ventoy终极指南&#xff1a;一个U盘启动所有系统&#xff0c;告别重复格式化烦恼 &#x1f60e; 【免费下载链接】Ventoy A new bootable USB solution. 项目地址: https://gitcode.com/GitHub_Trending/ve/Ventoy 还在为每次安装系统都要重新制作启动盘而烦恼吗&#x…...

AlphaFold 3终极指南:掌握Jackhmmer与HMMER提升蛋白质结构预测精度

AlphaFold 3终极指南&#xff1a;掌握Jackhmmer与HMMER提升蛋白质结构预测精度 【免费下载链接】alphafold3 AlphaFold 3 inference pipeline. 项目地址: https://gitcode.com/gh_mirrors/alp/alphafold3 你是否在蛋白质结构预测项目中遇到MSA生成效率低下的瓶颈&#x…...

Hitboxer:开源SOCD清理工具,3分钟提升游戏操作精准度

Hitboxer&#xff1a;开源SOCD清理工具&#xff0c;3分钟提升游戏操作精准度 【免费下载链接】socd Key remapper for epic gamers 项目地址: https://gitcode.com/gh_mirrors/so/socd 你是否在激烈的游戏对抗中经历过这样的挫败&#xff1a;同时按下左右方向键时角色卡…...

如何从零构建智能FOC轮腿机器人:完整开源硬件系统终极指南

如何从零构建智能FOC轮腿机器人&#xff1a;完整开源硬件系统终极指南 【免费下载链接】foc-wheel-legged-robot Open source materials for a novel structured legged robot, including mechanical design, electronic design, algorithm simulation, and software developme…...

为什么软件开发偏爱 Linux?深度剖析 Linux 相较于 Windows 的核心优势

引言 在软件开发的世界里&#xff0c;一个有趣的现象是&#xff1a;无论是大型互联网公司的服务器集群&#xff0c;还是资深程序员的个人开发机&#xff0c;Linux 操作系统的身影无处不在。与之形成鲜明对比的是&#xff0c;尽管 Windows 在个人消费市场占据绝对主导地位&…...

基于ESP32的智能电池充电器设计:多化学体系支持与模块化架构

1. 项目概述&#xff1a;打造一台全能的“电池医生”手头攒了一堆不同化学体系的电池&#xff0c;从航模用的4S锂聚合物电池&#xff0c;到应急灯里的12V铅酸电池&#xff0c;再到各种工具里的镍氢、锂离子电池&#xff0c;每次充电都得翻出好几个不同的充电器&#xff0c;桌面…...

告别元素变动导致的报错:探索自动化测试脚本的 AI“自愈”能力

前言:一个所有测试人都经历过的噩梦 周三晚上十一点,CI/CD流水线再次亮起红灯。 你打开日志,满屏的NoSuchElementException扑面而来。仔细一看——前端团队在昨天的版本中重构了登录页面的DOM结构,原本的#login-btn变成了#signin-button-v2,30个测试用例因此全军覆没。 …...

告别硬编码!在UE5.1里用蓝图动态配置MySQL连接参数(控件蓝图实战)

动态配置MySQL连接&#xff1a;UE5.1控件蓝图的工程化实践在游戏开发中&#xff0c;数据库连接往往是项目架构中不可或缺的一环。传统硬编码方式虽然简单直接&#xff0c;却带来了维护困难、安全性差、灵活性低等一系列问题。本文将深入探讨如何在UE5.1中构建一个完全动态化的M…...

简单学习 --> SSE

我们使用AI时&#xff0c;AI对我们说的话不会一次性把全部内容弹出来&#xff0c;而是会像流水一样&#xff0c;一点点吐出来&#xff0c;那么这种丝滑的交互体验&#xff0c;背后的核心就是 SSE (Server-Sent Events)。 什么是 SSE&#xff1f; SSE&#xff08;Server-Sent …...

Elden Ring帧率解锁终极指南:从60帧到144+的完整教程

Elden Ring帧率解锁终极指南&#xff1a;从60帧到144的完整教程 【免费下载链接】EldenRingFpsUnlockAndMore A small utility to remove frame rate limit, change FOV, add widescreen support and more for Elden Ring 项目地址: https://gitcode.com/gh_mirrors/el/Elden…...