深入分析 Android ContentProvider (五)

文章目录

    • 深入分析 Android ContentProvider (五)
    • ContentProvider 的性能优化和实践案例
      • 1. 性能优化技巧
        • 1.1. 数据库索引优化
          • 示例:添加索引
        • 1.2. 批量操作与事务管理
          • 示例:批量插入操作
        • 1.3. 使用异步操作
          • 示例:使用 AsyncTask 进行异步查询
        • 1.4. 缓存机制
          • 示例:使用 LruCache 进行内存缓存
        • 1.5. 使用 Loader 进行异步加载
          • 示例:使用 CursorLoader
      • 2. 实践案例
        • 2.1 案例一:消息应用的数据同步
          • 消息 ContentProvider 实现
        • 2.2 案例二:音乐播放器的媒体库管理
          • 媒体库 ContentProvider 实现
      • 3. 总结

深入分析 Android ContentProvider (五)

ContentProvider 的性能优化和实践案例

在实践中,合理的性能优化可以显著提升 ContentProvider 的效率和用户体验。以下是一些具体的性能优化技巧和实际案例,以便更好地理解和应用 ContentProvider。

1. 性能优化技巧

1.1. 数据库索引优化

在频繁进行查询操作的字段上添加索引,可以显著提高查询性能。数据库索引可以加快数据检索的速度,尤其是在大型数据集上。

示例:添加索引

在创建数据库表时,可以通过 SQL 语句为某些列创建索引:

private static final String CREATE_TABLE ="CREATE TABLE " + TABLE_NAME + " (" +COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +COLUMN_NAME + " TEXT NOT NULL);";private static final String CREATE_INDEX ="CREATE INDEX index_name ON " + TABLE_NAME + " (" + COLUMN_NAME + ");";@Override
public void onCreate(SQLiteDatabase db) {db.execSQL(CREATE_TABLE);db.execSQL(CREATE_INDEX);
}
1.2. 批量操作与事务管理

在执行大批量的数据插入、更新或删除操作时,使用事务可以减少数据库锁的开销,并提高操作的整体性能。

示例:批量插入操作
public void bulkInsertData(List<ContentValues> valuesList) {SQLiteDatabase db = dbHelper.getWritableDatabase();db.beginTransaction();try {for (ContentValues values : valuesList) {db.insertOrThrow(TABLE_NAME, null, values);}db.setTransactionSuccessful();} finally {db.endTransaction();}
}
1.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/examples");return getContentResolver().query(uri, null, null, null, "name ASC");}@Overrideprotected void onPostExecute(Cursor cursor) {if (cursor != null) {// 处理查询结果cursor.close();}}
}
1.4. 缓存机制

在数据访问频繁的场景中,使用缓存机制可以显著提高性能。可以选择内存缓存(如 LruCache)或磁盘缓存来缓存常用数据,减少数据库查询的次数。

示例:使用 LruCache 进行内存缓存
private LruCache<String, Bitmap> memoryCache;public void initCache() {final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);final int cacheSize = maxMemory / 8;memoryCache = new LruCache<>(cacheSize);
}public void addBitmapToCache(String key, Bitmap bitmap) {if (getBitmapFromCache(key) == null) {memoryCache.put(key, bitmap);}
}public Bitmap getBitmapFromCache(String key) {return memoryCache.get(key);
}
1.5. 使用 Loader 进行异步加载

Loader 可以在异步线程中加载数据,避免主线程阻塞,并在数据加载完成时自动更新 UI。

示例:使用 CursorLoader
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/examples");return new CursorLoader(this, uri, null, null, null, "name ASC");}@Overridepublic void onLoadFinished(@NonNull Loader<Cursor> loader, Cursor data) {// 更新 UI}@Overridepublic void onLoaderReset(@NonNull Loader<Cursor> loader) {// 清理资源}
}

2. 实践案例

2.1 案例一:消息应用的数据同步

在消息应用中,消息数据通常需要在客户端和服务器之间同步。使用 ContentProvider,可以方便地实现数据的本地存储和跨进程访问,同时结合 Loader 和异步任务,确保数据加载和更新的流畅性。

消息 ContentProvider 实现
public class MessageProvider extends ContentProvider {private static final String AUTHORITY = "com.example.provider";private static final String BASE_PATH = "messages";public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH);private static final int MESSAGES = 1;private static final int MESSAGE_ID = 2;private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);static {uriMatcher.addURI(AUTHORITY, BASE_PATH, MESSAGES);uriMatcher.addURI(AUTHORITY, BASE_PATH + "/#", MESSAGE_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 MESSAGES:return database.query(DatabaseHelper.TABLE_MESSAGES, projection, selection, selectionArgs, null, null, sortOrder);case MESSAGE_ID:selection = DatabaseHelper.COLUMN_ID + "=?";selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};return database.query(DatabaseHelper.TABLE_MESSAGES, 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_MESSAGES, 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 MESSAGES:rowsDeleted = database.delete(DatabaseHelper.TABLE_MESSAGES, selection, selectionArgs);break;case MESSAGE_ID:selection = DatabaseHelper.COLUMN_ID + "=?";selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};rowsDeleted = database.delete(DatabaseHelper.TABLE_MESSAGES, 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 MESSAGES:rowsUpdated = database.update(DatabaseHelper.TABLE_MESSAGES, values, selection, selectionArgs);break;case MESSAGE_ID:selection = DatabaseHelper.COLUMN_ID + "=?";selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};rowsUpdated = database.update(DatabaseHelper.TABLE_MESSAGES, 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 MESSAGES:return "vnd.android.cursor.dir/vnd.com.example.provider.messages";case MESSAGE_ID:return "vnd.android.cursor.item/vnd.com.example.provider.message";default:throw new IllegalArgumentException("Unknown URI: " + uri);}}
}
2.2 案例二:音乐播放器的媒体库管理

在音乐播放器应用中,媒体库管理需要高效的数据存储和查询功能。ContentProvider 可以为应用提供统一的数据访问接口,并结合批量操作和事务管理,实现高效的数据管理。

媒体库 ContentProvider 实现
public class MediaProvider extends ContentProvider {private static final String AUTHORITY = "com.example.provider";private static final String BASE_PATH = "media";public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH);private static final int MEDIA = 1;private static final int MEDIA_ID = 2;private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);static {uriMatcher.addURI(AUTHORITY, BASE_PATH, MEDIA);uriMatcher.addURI(AUTHORITY, BASE_PATH + "/#", MEDIA_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 MEDIA:return database.query(DatabaseHelper.TABLE_MEDIA, projection, selection, selectionArgs, null, null, sortOrder);case MEDIA_ID:selection = DatabaseHelper.COLUMN_ID + "=?";selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};return database.query(DatabaseHelper.TABLE_MEDIA, 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_MEDIA, 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 MEDIA:rowsDeleted = database.delete(DatabaseHelper.TABLE_MEDIA, selection, selectionArgs);break;case MEDIA_ID:selection = DatabaseHelper.COLUMN_ID + "=?";selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};rowsDeleted = database.delete(DatabaseHelper.TABLE_MEDIA, 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 MEDIA:rowsUpdated = database.update(DatabaseHelper.TABLE_MEDIA, values, selection, selectionArgs);break;case MEDIA_ID:selection = DatabaseHelper.COLUMN_ID + "=?";selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};rowsUpdated = database.update(DatabaseHelper.TABLE_MEDIA, 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 MEDIA:return "vnd.android.cursor.dir/vnd.com.example.provider.media";case MEDIA_ID:return "vnd.android.cursor.item/vnd.com.example.provider.media";default:throw new IllegalArgumentException("Unknown URI: " + uri);}}
}

3. 总结

ContentProvider 是 Android 中强大的数据共享和管理机制,尤其适用于跨进程数据共享和提供统一的数据访问接口。在实际应用中,通过合理设计和优化,可以充分发挥 ContentProvider 的优势,确保数据操作的高效性和安全性。遵循最佳实践并结合具体场景进行性能优化,可以显著提升应用的用户体验和稳定性。

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

在这里插入图片描述

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

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

相关文章

Nodejs实现微信订阅消息的发送

关于Nodejs的项目配置和路由配置我这里就不过多叙述了。着重关于订阅消息的发送 1.首先前往微信开发者平台配置好自己的订阅消息模板&#xff08;改版后的只支持一次性订阅&#xff1a;每次用户操作记录一次&#xff0c;openid只能发送一次消息给用户&#xff0c;不能持续订阅…

每日一知识点- Java 方法重载和方法重写

目录 &#x1f4dd; 每日一知识点方法重载方法重写 &#x1f4ce; 参考文章 &#x1f600; 准备好了吗&#xff1f;让我们一起步入这座Java神奇的城堡&#xff0c;揭开方法重载&#xff08;Overloading&#xff09;和方法重写&#xff08;Overriding&#xff09;的神秘面纱。 &…

基于迁移学习的手势分类模型训练

1、基本原理介绍 这里介绍的单指模型迁移。一般我们训练模型时&#xff0c;往往会自定义一个模型类&#xff0c;这个类中定义了神经网络的结构&#xff0c;训练时将数据集输入&#xff0c;从0开始训练&#xff1b;而迁移学习中&#xff08;单指模型迁移策略&#xff09;&#x…

一文掌握YOLOv1-v10

引言 YOLO目标检测算法&#xff0c;不过多介绍&#xff0c;是基于深度学习的目标检测算法中最出名、发展最好的检测器&#xff0c;没有之一。本文简要的介绍一下从YOLOv1-YOLOv10的演化过程&#xff0c;详细技术细节不过多介绍&#xff0c;只提及改进点&#xff0c;适合初学者…

Vue3二次封装axios

官网: https://www.axios-http.cn/docs/interceptors steps1: 安装 npm install axios -ssteps2: /src/api/request.js 文件 >>> 拦截器 import axios from axios // 如果没用element-plus就不引入 import { ElMessage } from element-plusconst service axios.cre…

7月22日学习笔记 文件共享服务nfs,SAMBA文件共享与DNS域名服务

任务背景 由于业务驱动&#xff0c;为了提⾼⽤户的访问效率&#xff0c;现需要将原有web服务器上的静态资源 ⽂件分离出来&#xff0c;单独保存到⼀台⽂件服务器上。 任务要求 1. ⼀台应⽤服务器web-server部署apache&#xff0c;静态⽹⻚资源存放在另外⼀台NFS服 务器上 …

四、GD32 MCU 常见外设介绍 (2) GPIO 模块介绍

2.GPIO 模块介绍 GPIO的全称为通用输入输出口&#xff0c;是很多外设能够正常工作的必要条件。除了一些特定功能的引脚(如电源脚)外&#xff0c;MCU上其他的引脚都可以当做GPIO来使用。本章&#xff0c;我们将对GPIO进行简单介绍&#xff0c;并通过一个“流水灯”的实验来熟悉…

MATLAB基础:数组及其数学运算

今天我们继续学习MATLAB中的数组 我们在学习MATLAB时了解到&#xff0c;MATLAB作者秉持着“万物皆可矩阵”的思想企图将数学甚至世间万物使用矩阵表示出来&#xff0c;而矩阵的处理&#xff0c;自然成了这门语言的重中之重。 数组基础 在MATLAB中&#xff0c;数组是一个基本…

【人工智能 | 机器学习 | 理论篇】线性模型

文章目录 1. 基本形式2. 线性回归3. 对数几率回归4. 线性判别分析5. 多分类学习6. 类别不平衡问题 1. 基本形式 设有 d 个属性描述的示例 x ( x 1 , x 2 , x 3 , . . . , x d ) x ({x_1, x_2, x_3, ..., x_d}) x(x1​,x2​,x3​,...,xd​) 线性模型&#xff08;linear mode…

使用C#手搓Word插件

WordTools主要功能介绍 编码语言&#xff1a;C#【VSTO】 1、选择 1.1、表格 作用&#xff1a;全选文档中的表格&#xff1b; 1.2、表头 作用&#xff1a;全选文档所有表格的表头【第一行】&#xff1b; 1.3、表正文 全选文档中所有表格的除表头部分【除第一行部分】 1.…

Android AI应用开发:移动检测

基于Google ML模型的Android移动物体检测应用——检测、跟踪视频中的物体 A. 项目描述 ML Kit物体检测器可以对视频流进行操作&#xff0c;能够检测视频中的物体并在连续视频帧中跟踪该物体。 相机捕捉视频时&#xff0c;检测到移动物体并为其生成一个边界框&#xff0c;并分…

【性能测试-登录时密码加密存储如何传参】

目的】 登录接口&#xff0c;密码加密传输&#xff0c;开发不做处理的情况下&#xff0c;密码如何加密传输 【方案】 使用前置处理器&#xff1a;JSR223 预处理程序&#xff0c;主要是在执行登录接口前将密码按照加密算法获得对应的加密密码&#xff0c;并传入接口 【说明】前…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 亲子游戏(200分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 🍿 最新华为OD机试D卷目录,全、新、准,题目覆盖率达 95% 以上,支持题目在线…

【BUG】已解决:TypeError: a bytes-like object is required, not ‘str‘

TypeError: a bytes-like object is required, not ‘str‘ 目录 TypeError: a bytes-like object is required, not ‘str‘ 【常见模块错误】 【解决方案】 错误原因分析 解决方案 示例代码 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998https://bbs.csdn.net…

基于扩散的生成模型的语音增强和去噪

第二章 目标说话人提取之《Speech Enhancement and Dereverberation with Diffusion-based Generative Models》 文章目录 前言一、任务二、动机三、挑战四、方法1.方法:基于分数的语音增强生成模型(sgmse)2.网络结构 五、实验评价1.数据集2.采样器设置和评价指标3.基线模型4.评…

PaliGemma:A versatile 3B VLM for transfer

1.model 1.1 Architecture 图像分辨率为固定的正方形,224,448,896,这导致每种模型都有固定数量的图像token,256,1024,4096。图像在最前面,无需特殊的位置标记,BOS标记文本的开始,\n作为SEP token,不出现在前缀中,单独对SEP进行标记,以避免它与前缀的结束或后缀的…

力扣94题(java语言)

题目 思路 使用一个栈来模拟递归的过程&#xff0c;以非递归的方式完成中序遍历(使用栈可以避免递归调用的空间消耗)。 遍历顺序步骤&#xff1a; 遍历左子树访问根节点遍历右子树 package algorithm_leetcode;import java.util.ArrayList; import java.util.List; import…

立仪光谱共焦传感器应用测量之:汽车连接器高度差测量

01 检测要求&#xff0c;要求测量汽车连接器的高度差 02 检测方式 根据观察&#xff0c;我们采用立仪科技光谱共焦H4UC控制器搭配D65A52系列镜头&#xff0c;角度最大&#xff0c;外径最大&#xff0c;量程大&#xff0c;可以有效应用于测量弧面&#xff0c;大角度面等零件。 0…

SAPUI5基础知识19 - 视图嵌套(Nested Views)

1. 背景 SAPUI5 是一个用于构建企业级 Web 应用程序的 JavaScript 框架。它提供了丰富的 UI 控件和工具&#xff0c;帮助开发者创建复杂的用户界面。Nested Views 是 SAPUI5 中的一种设计模式&#xff0c;允许在一个视图中嵌套另一个视图。这种模式有助于模块化和重用代码&…

什么是反射以及反射的应用及例子

反射是Java中框架设计的核心&#xff0c;通过对类的构造、属性、方法等数据的获取提供抽象的底层构建。 反射机制&#xff1a; 反射需要先获得类的class字节码&#xff0c;由JVM类加载器(ClassLoader)负责加载&#xff0c;并在内存中缓存class的内部结构。借助于Java的反射机制…