深入分析 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,可以大幅提升应用的性能和用户体验。

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

在这里插入图片描述

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

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

相关文章

【工具】轻松转换JSON与Markdown表格——自制Obsidian插件

文章目录 一、插件简介二、功能详解三、使用教程四、插件代码五、总结 一、插件简介 JsonMdTableConverter是一款用于Obsidian的插件&#xff0c;它可以帮助用户在JSON格式和Markdown表格之间进行快速转换。这款插件具有以下特点&#xff1a; 轻松识别并转换JSON与Markdown表格…

60个常见的 Linux 指令

1.ssh 登录到计算机主机 ssh -p port usernamehostnameusername&#xff1a; 远程计算机上的用户账户名。 hostname&#xff1a; 远程计算机的 IP 地址或主机名。 -p 选项指定端口号。 2.ls 列出目录内容 ls ls -l # 显示详细列表 ls -a # 显示包括隐藏文件在内的所有内…

【GD32】从零开始学GD32单片机 | 基于SD卡的FatFs文件系统移植(GD32F470ZGT6)

1. 简介 FatFs是一个专门为微处理器设计的通用文件系统&#xff0c;像8051、AVR、PIC、ARM架构的微处理器都能兼容该文件系统。 FatFs文件系统最大的一个优点是它是DOS和Windows兼容的&#xff0c;这意味着你只需要再移植一个USB驱动就可以实现在电脑中访问单片机的储存结构&…

Cookie与Session 实现登录操作

Cookie Cookie 是网络编程中使用最广泛的一项技术&#xff0c;主要用于辨识用户身份。 客户端&#xff08;浏览器&#xff09;与网站服务端通讯的过程如下图所示&#xff1a; 从图中看&#xff0c;服务端既要返回 Cookie 给客户端&#xff0c;也要读取客户端提交的 Cookie。所…

Domainim:一款高效的企业级网络安全扫描工具

关于Domainim Domainim是一款功能强大的企业级网络安全扫描工具&#xff0c;该工具运行效率高&#xff0c;功能完善&#xff0c;可以帮助广大研究人员针对企业或组织网络执行大规模安全扫描任务。 该工具可以快速执行网络安全扫描和域名/子域名网络侦查任务&#xff0c;旨在使…

python毕业设计选题协同过滤算法在音乐推荐系统

✌网站介绍&#xff1a;✌10年项目辅导经验、专注于计算机技术领域学生项目实战辅导。 ✌服务范围&#xff1a;Java(SpringBoo/SSM)、Python、PHP、Nodejs、爬虫、数据可视化、小程序、安卓app、大数据等设计与开发。 ✌服务内容&#xff1a;免费功能设计、免费提供开题答辩P…

暑期C++ 缺省参数

有任何不懂的问题可以评论区留言&#xff0c;能力范围内都会一一回答 1.缺省参数的概念 缺省参数是是声明或定义参数时为函数的参数指定一个缺省值。在调用该函数值时&#xff0c;如果没有指定实参则采用该形参的缺省值&#xff0c;否则使用指定的实参 看了上面定义后&#…

【零基础必看的前端教程】——JavaScript(七)数组

欢迎大家打开前端的新篇章——JavaScript&#xff0c;JavaScript与HTML、CSS合称为前端三大件&#xff0c;JavaScript是前端的重中之重&#xff0c;小洪将继续以零基础视角&#xff0c;带你循序渐进学习前端知识&#xff0c;一看就懂&#xff0c;小白也能转行做前端&#xff01…

vue3实现在新标签中打开指定的网址

有一个文件列表&#xff0c;如下图&#xff1a; 我希望点击查看按钮的时候&#xff0c;能够在新的标签页面打开这个文件的地址进行预览&#xff0c;该如何实现呢&#xff1f; 比如&#xff1a; 实际上要实现这个并不难&#xff0c;参考demo如下&#xff1a; 首先&#x…

渗透测试——利用公网反弹shell到本地的两种方式,vmware虚拟机与主机的端口转发,本地ssh无法上线的问题解决

解决问题&#xff1a; 因长期使用本地模拟靶场&#xff0c;实战护网时并非模拟靶场&#xff0c;shell反弹需要利用公网测试。解决目标站无法反弹到本地的情况。解决本地是windows&#xff0c;虚拟机是kail、linux&#xff0c;无法相互转换流量的情况。 环境搭建 靶机 centOS7 …

VScode 批量操作

VScode 批量操作 批量修改 按住 alt/option 键&#xff0c; 选择需要批量操作的位置 如果是多行&#xff0c;则按住 altshift 键 可以直接操作 但是有时候比如变量命名&#xff0c;可能需要递增操作的命名 需要下载插件 Increment Selection 按照1的方法多选光标之后&am…

html+css+js前端作业 王者荣耀官网5个页面带js

htmlcssjs前端作业 王者荣耀官网5个页面带js 下载地址 https://download.csdn.net/download/qq_42431718/89574989 目录1 目录2 目录3 项目视频 王者荣耀5个页面&#xff08;带js&#xff09; 页面1 页面2 页面3 页面4 页面5

php接口返回的json字符串,json_decode()失败,原来是多了红点

问题&#xff1a; 调用某个接口返回的json&#xff0c;json_decode()失败&#xff0c;返回数据为null&#xff0c; echo json_last_error();返回错误码 4 经过多次调试发现&#xff1a;多出来一个红点&#xff0c;预览是看不到的。 解决&#xff1a;要去除BOM头部 $resul…

vue 搜索框

效果 创建搜索组件&#xff1a; 在Vue项目中&#xff0c;首先需要创建一个搜索组件。这个组件通常包含一个输入框和一个搜索按钮。使用v-model指令将输入框与组件的数据属性&#xff08;如searchKeyword&#xff09;进行双向绑定&#xff0c;以便获取用户输入的关键词。处理搜索…

Linux网络:传输层协议TCP(二)三次挥手四次握手详解

目录 一、TCP的连接管理机制 1.1三次握手 1.2四次挥手 二、理解 TIME_WAIT 状态 2.1解决TIME_WAIT 状态引起的 bind 失败的方法 三、理解CLOSE_WAIT状态 一、TCP的连接管理机制 在正常情况下, TCP 要经过三次握手建立连接, 四次挥手断开连接 1.1三次握手 三次握手顾名思…

Docker从零开始:安装、部署到卸载,一文搞定全流程

Docker是一种开源容器化平台&#xff0c;它允许开发者将应用程序及其依赖打包成轻量级、可移植的容器。这些容器能确保软件在任何环境中稳定运行&#xff0c;无论是开发者的笔记本电脑还是生产服务器。Docker流行的原因在于其提供的隔离性、可移植性和可扩展性&#xff0c;它简…

2024年展望:人工智能领域将呈现怎样的发展趋势?

2024年&#xff0c;人工智能&#xff08;AI&#xff09;领域将继续保持强劲的发展势头&#xff0c;并呈现出多个重要的发展趋势。以下是对该领域未来发展趋势的详细展望&#xff1a; 一、技术创新与融合 多模态生成式AI的崛起&#xff1a; 多模态生成式AI系统能够处理文本、声…

C# 将字符串数组以树型结构化

例如字符串数组&#xff1a; string[] arr { "1","3-4-5-6-7", "2","3-4","3-4-5","3-4-5-6", "3", "6", "4", "6-1", "6-2", "5", "6-1-1&…

李艳波医生怎么挂号?

对于想要预约李艳波医生的患者来说&#xff0c;北京仁爱堂提供了两种便捷的预约方式&#xff1a;来院面诊和视频会诊。来院面诊是传统的就诊方式&#xff0c;患者可以直接前往仁爱堂&#xff0c;与李艳波医生面对面交流&#xff0c;详细了解自己的病情并接受专业的治疗建议。这…

解决Github Copilot无效,无法使用的问题

如果是在Copilot的终端报错 Invalid copilot token: missing token: 403 原因有三种 1&#xff0c;你的账号没有订阅正版的服务&#xff0c;解决办法是购买正版服务 2&#xff0c;你在购买服务的时候&#xff0c;Github上 billing information 地址信息和支付卡片的地址信息不…