深入分析 Android ContentProvider (三)

news2024/12/26 15:35:45

文章目录

    • 深入分析 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;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_example);

        getSupportLoaderManager().initLoader(LOADER_ID, null, this);
    }

    @NonNull
    @Override
    public 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");
    }

    @Override
    public void onLoadFinished(@NonNull Loader<Cursor> loader, Cursor data) {
        // 处理加载完成的数据
    }

    @Override
    public 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" />
<provider
    android: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> {
    @Override
    protected Cursor doInBackground(Void... voids) {
        Uri uri = Uri.parse("content://com.example.provider/example");
        return getContentResolver().query(uri, null, null, null, "name ASC");
    }

    @Override
    protected 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.coloradmin.cn/o/1947680.html

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

相关文章

On the Dimensionality of Word Embedding论文解读

基本信息 作者Zi Yindoi10.3115/v1/D14-1162发表时间2018期刊NIPS网址https://arxiv.org/abs/1812.04224 研究背景 1. What’s known 既往研究已证实 词嵌入的一元不变性。 多数的词嵌入算法本质上都是矩阵分解。 2. What’s new 创新点 提出了 Pairwise Inner Product&…

Prometheus配置alertmanager告警

1、拉取镜像并运行 1、配置docker镜像源 [rootlocalhost ~]# vim /etc/docker/daemon.json {"registry-mirrors": ["https://dfaad.mirror.aliyuncs.com"] } [rootlocalhost ~]# systemctl daemon-reload [rootlocalhost ~]# systemctl restart docker2、…

单片机主控的基本电路

论文 1.复位电路 2.启动模式设置接口 3.VBAT供电接口 4.MCU 基本电路 5.参考电压选择端口 6.SDRAM电路 7.LCD模块电路 8.USB电路 9.按键电路 10.LED电路 11.SD卡电路 12.电量检测电路 13.蓝牙接口通信电路 14.SPI FLASH 电路

Spark实时(四):Strctured Streaming简单应用

文章目录 Strctured Streaming简单应用 一、Output Modes输出模式 二、Streaming Table API 三、​​​​​​​​​​​​​​Triggers 1、​​​​​​​unspecified&#xff08;默认模式&#xff09; 2、​​​​​​​​​​​​​​Fixed interval micro-batches&am…

总结20个Python接单赚钱的平台,兼职月入6000+_让你早日实现财富自由

今天就给大家盘点几个基本入门接私活的资源&#xff0c;让你轻松学python&#xff0c;实现经济独立。 一、Python兼职种类&#xff1a; 接私活刚学会python那会&#xff0c;就有认识的朋友介绍做一个网站的私活&#xff0c;当时接单赚了4K&#xff0c;后又自己接过开发网站后…

vue3+element-plus 实现动态菜单和动态路由的渲染

在 Vue.js 中&#xff0c;使用 Vue Router 管理路由数据&#xff0c;并将其用于渲染 el-menu&#xff08;Element UI 的菜单组件&#xff09;通常涉及以下几个步骤&#xff1a; 定义路由元数据&#xff1a; 在你的路由配置中&#xff0c;为每个路由项添加 meta 字段&#xff0c…

SQL labs-SQL注入(五,使用sqlmap进行cookie注入)

本文仅作为学习参考使用&#xff0c;本文作者对任何使用本文进行渗透攻击破坏不负任何责任。 引言&#xff1a; Cookie 是一些数据, 存储于你电脑上的文本文件中。当 web 服务器向浏览器发送 web 页面时&#xff0c;在连接关闭后&#xff0c;服务端不会记录用户的信息。Cookie…

新形势下职业教育大数据人才培养策略

一、引言 随着信息技术的飞速发展&#xff0c;大数据已成为驱动经济社会变革的关键力量。在新形势下&#xff0c;职业教育作为技术技能人才培养的重要阵地&#xff0c;面临着如何适应大数据时代要求、提升人才培养质量的紧迫任务。当前&#xff0c;职业教育在大数据人才培养方…

【C语言】指针大小知多少 ?一场探寻C语言深处的冒险 !

目录 C语言中指针的大小1. 指针大小的基本概念1.1 32位系统1.2 64位系统 2. 指针大小示例2.1 32位系统输出2.2 64位系统输出 3. 指针大小与数据类型无关示例输出示例 4. 跨平台的指针大小示例输出示例 5. 关键点总结5.1 指针大小与平台关系5.2 跨平台编程注意事项 6. 指针大小示…

PySide(PyQt)的小部件通过伪状态以及自定义特性改变外观

1、通过伪状态来改变外观 伪状态是一种特殊的状态&#xff0c;通常用于描述控件在特定条件下的外观变化。这些状态不是控件的实际属性&#xff0c;而是用于在样式表中应用不同样式的标记。 以QPushButton为例。在 PySide6 中&#xff0c;QPushButton 具有多种伪状态&#xff0c…

卷积神经网络(二)-AlexNet

前言&#xff1a; AlexNet是2012年ImageNet竞赛冠军&#xff08;以领先第二名10%的准确率夺得冠军&#xff09;获得者Hinton和他的学生Alex Krizhevsky设计的,在ILSVRC-2010测试集上取得了top-1错误率37.5%,top-5错误率17.0%&#xff08;优于第二名的16.4%&#xff09;,明显优…

科技快讯丨智驱未来,校企共融:浪潮海岳携手山东大学软件学院开展低代码开发实训活动

近日&#xff0c;山东大学软件学院暑期实训活动圆满落幕。作为领先的企业数字化转型优秀服务商&#xff0c;浪潮海岳主导的低代码开发课题吸引了众多师生参训&#xff0c;取得了良好成效。 当前&#xff0c;低代码开发已成为软件行业降本增效、提升用户体验的必然选择&#xff…

labview实现两台电脑共享变量传输及同步

因为工作需要&#xff0c;需要实现多台主机间进行数据传输&#xff0c; 有两个备选方案&#xff0c; 1&#xff1a;建立tcp&#xff0c;然后自己解包 2&#xff1a;就是通过共享变量传输 虽然共享变量也是建立在TCP/IP上面的&#xff0c;但是不用自己解包呀 关于共享变量网络上…

vivo手机恢复出厂设置在哪里?清除数据后如何找回?2个技巧

随着使用时间的增长&#xff0c;手机可能会因为累积的缓存文件、不必要的数据或软件问题而出现性能下降或系统运行缓慢。为了解决这些问题&#xff0c;执行恢复出厂设置成为了一种流行的解决方案。那么&#xff0c;vivo手机恢复出厂设置在哪里&#xff1f;数据清除后该如何找回…

CCRC-DSO数据安全官:打造数据“冷链”,做强做大数据产业

在7月22日国新办举办的“推动高质量发展”系列新闻发布会上&#xff0c;国家数据局局长刘烈宏宣布&#xff0c;为响应党的二十届三中全会的决策&#xff0c;将加速推进数字经济发展机制的构建和完善数据要素市场制度。 他强调了对地方试点探索的支持&#xff0c;目标是建立强大…

基础复习(数组)

数组 一维数组 1.静态初始化 数据类型[] 数组名 new 数据类型[]{元素1,元素2,元素3,...}; 数据类型[] 数组名 {元素1,元素2,元素3...}; 2.动态初始化 数组存储的元素的数据类型[] 数组名字 new 数组存储的元素的数据类型[长度]; 3.执行原理 变量存储的是数组的地址值。…

Pyqt5新手教程

PyQt界面开发的两种方式&#xff1a;可视化UI 编程式UI &#xff08;1&#xff09;可视化UI&#xff1a;基于Qt Designer可视化编辑工具进行组件拖放、属性设置、布局管理等操作创建界面。 一是将其保存为.ui文件&#xff0c;然后在PyQt应用程序中加载和使用.ui文件。 二是使用…

接口自动化测试框架实战-3-文件读写封装

上一小节我们详细介绍了项目中所使用的接口文档&#xff0c;本小节我们将进入到接口测试框架第一个部分通用函数commons的开发&#xff0c;本小节我们重点完成文件读写方法的封装。 首先为什么要封装文件读写的方法&#xff0c;原因有如下几点&#xff1a; 读接口配置&#x…

B站音视频分开 大小问题

音频是33331 kb&#xff0c;视频是374661 kb 合并之后却是2561363 kb 这可能是B站音频和视频分开的原因吧

html实现酷炫美观的可视化大屏(十种风格示例,附源码)

文章目录 完整效果演示1.蓝色流线风的可视化大屏1.1 大屏效果1.2 大屏代码1.3 大屏下载 2.地图模块风的可视化大屏2.1 大屏效果2.2 大屏代码2.3 大屏下载 3.科技轮动风的可视化大屏3.1 大屏效果3.2 大屏代码3.3 大屏下载 4.蓝色海洋风的可视化大屏4.1 大屏效果4.2 大屏代码4.3 …