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

深入分析 Android ContentProvider (十)

文章目录

    • 深入分析 Android ContentProvider (十)
    • ContentProvider 的高级使用及最佳实践(续)
      • 1. ContentProvider 与异步加载
        • 使用 CursorLoader 进行异步数据加载
      • 2. 动态权限请求
        • 动态请求权限示例
      • 3. ContentProvider 的缓存优化
        • 使用 LruCache 实现内存缓存
      • 4. ContentProvider 的安全性
        • 1. 权限控制
        • 2. 数据加密
        • 示例:使用 AES 加密数据
      • 5. ContentProvider 的多进程支持
        • 示例:多进程 ContentProvider
      • 6. 总结

深入分析 Android ContentProvider (十)

ContentProvider 的高级使用及最佳实践(续)

1. ContentProvider 与异步加载

在 Android 应用开发中,响应 UI 的数据加载应该尽量在异步线程中进行,以避免阻塞主线程,提升用户体验。Loaders 和 ContentProvider 可以结合使用,实现高效的数据加载。

使用 CursorLoader 进行异步数据加载

CursorLoader 是一个专门用于 ContentProvider 的 Loader 类,能够在后台线程中执行查询操作,并在数据改变时自动刷新。

public class MyActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor> {private static final int LOADER_ID = 1;private MyAdapter adapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);adapter = new MyAdapter(this, null);ListView listView = findViewById(R.id.listView);listView.setAdapter(adapter);getLoaderManager().initLoader(LOADER_ID, null, this);}@NonNull@Overridepublic Loader<Cursor> onCreateLoader(int id, @Nullable Bundle args) {return new CursorLoader(this, MyContentProvider.CONTENT_URI, null, null, null, null);}@Overridepublic void onLoadFinished(@NonNull Loader<Cursor> loader, Cursor data) {adapter.swapCursor(data);}@Overridepublic void onLoaderReset(@NonNull Loader<Cursor> loader) {adapter.swapCursor(null);}
}

在这个示例中,CursorLoader 负责在后台线程中执行查询操作,当数据加载完成后会自动更新 UI。

2. 动态权限请求

从 Android 6.0 (API level 23) 开始,应用在运行时需要动态请求权限。对于 ContentProvider,通常涉及到对存储或联系人等敏感数据的访问权限。

动态请求权限示例
public class MyActivity extends AppCompatActivity {private static final int PERMISSIONS_REQUEST_READ_CONTACTS = 100;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, PERMISSIONS_REQUEST_READ_CONTACTS);} else {loadContacts();}}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {if (requestCode == PERMISSIONS_REQUEST_READ_CONTACTS) {if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {loadContacts();} else {Toast.makeText(this, "Permission denied to read contacts", Toast.LENGTH_SHORT).show();}}}private void loadContacts() {// 执行联系人加载操作}
}

动态请求权限可以确保在用户明确授权后才进行敏感数据操作,提升应用的安全性。

3. ContentProvider 的缓存优化

为了提升 ContentProvider 的性能,可以使用内存缓存或磁盘缓存来减少数据库访问次数。可以使用 LruCache 或 DiskLruCache 来实现。

使用 LruCache 实现内存缓存
public class MyContentProvider extends ContentProvider {private static LruCache<String, Bitmap> memoryCache;@Overridepublic boolean onCreate() {final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);final int cacheSize = maxMemory / 8;memoryCache = new LruCache<>(cacheSize);return true;}public static void addBitmapToMemoryCache(String key, Bitmap bitmap) {if (getBitmapFromMemCache(key) == null) {memoryCache.put(key, bitmap);}}public static Bitmap getBitmapFromMemCache(String key) {return memoryCache.get(key);}@Nullable@Overridepublic Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,@Nullable String[] selectionArgs, @Nullable String sortOrder) {// 查询逻辑,并从缓存中读取数据return null;}
}

通过 LruCache,我们可以在内存中缓存常用的数据,减少频繁的数据库查询,提高访问速度。

4. ContentProvider 的安全性

在设计 ContentProvider 时,安全性是一个关键问题。为了确保数据的安全,可以使用以下几种方法:

1. 权限控制

通过定义权限,限制哪些应用可以访问 ContentProvider。

<providerandroid:name=".MyContentProvider"android:authorities="com.example.provider"android:exported="true"android:permission="com.example.provider.READ_WRITE">
</provider>
2. 数据加密

对于敏感数据,可以在存储前进行加密,读取时进行解密,确保数据在存储介质中的安全。

示例:使用 AES 加密数据
public class EncryptionHelper {private static final String ALGORITHM = "AES";private static final String TRANSFORMATION = "AES";public static byte[] encrypt(String key, byte[] data) throws Exception {Cipher cipher = Cipher.getInstance(TRANSFORMATION);cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getBytes(), ALGORITHM));return cipher.doFinal(data);}public static byte[] decrypt(String key, byte[] data) throws Exception {Cipher cipher = Cipher.getInstance(TRANSFORMATION);cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key.getBytes(), ALGORITHM));return cipher.doFinal(data);}
}

通过加密敏感数据,可以有效防止数据泄露和未授权访问。

5. ContentProvider 的多进程支持

在多进程应用中,ContentProvider 可以实现跨进程数据共享。通过设置 android:process 属性,可以指定 ContentProvider 运行在不同的进程中。

示例:多进程 ContentProvider
<providerandroid:name=".MyContentProvider"android:authorities="com.example.provider"android:process=":remote"android:exported="true">
</provider>

通过指定 android:process 属性,可以让 ContentProvider 运行在一个独立的进程中,提高应用的稳定性和安全性。

6. 总结

ContentProvider 是 Android 中实现数据共享和管理的重要组件,通过深入理解和灵活运用,可以实现高效、安全的数据操作。通过结合 Loaders 实现异步数据加载,使用缓存提升性能,动态请求权限确保安全,设计合理的 URI 结构和权限管理,可以大幅提升 ContentProvider 的使用效果。在实际开发中,结合具体需求和场景,灵活应用这些高级技巧和最佳实践,是开发高性能、稳定 Android 应用的关键。通过具体的代码示例和实践案例,我们展示了 ContentProvider 的广泛应用和最佳实践,为开发者提供了丰富的参考。

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

在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【C语言】宏定义常量加 ; 的错误
  • 第一阶段面试问题(前半部分)
  • 基于Vue的实时单号采集与校验系统开发:扫码枪自动输入与后台验证
  • 利用人工智能ChatGPT自动生成基于PO的数据驱动测试框架
  • 关于python问题 ,生成的excel文件内无爬取的数据存在,请问应如何解决?
  • 花10分钟写个漂亮的后端API接口模板!
  • 【架构】客户端优化
  • vue3后台管理系统 vue3+vite+pinia+element-plus+axios上
  • 基于Python的鸢尾花聚类与分类
  • VS+opencv+环境配置
  • QEMU虚拟机(TODO)
  • 【Spring】——代理模式、AOP、MyBatis-Spring学习以及Spring事务
  • WPF中的数据模板和样式:实现一致性和可维护性
  • openmetadata安装
  • 赞!蚓链用数字化打造助农扶农电商平台!
  • 【每日笔记】【Go学习笔记】2019-01-10 codis proxy处理流程
  • 【跃迁之路】【669天】程序员高效学习方法论探索系列(实验阶段426-2018.12.13)...
  • happypack两次报错的问题
  • Javascript设计模式学习之Observer(观察者)模式
  • js对象的深浅拷贝
  • JS进阶 - JS 、JS-Web-API与DOM、BOM
  • linux安装openssl、swoole等扩展的具体步骤
  • Linux中的硬链接与软链接
  • Tornado学习笔记(1)
  • TypeScript实现数据结构(一)栈,队列,链表
  • vue2.0项目引入element-ui
  • Web设计流程优化:网页效果图设计新思路
  • 从@property说起(二)当我们写下@property (nonatomic, weak) id obj时,我们究竟写了什么...
  • 前端 CSS : 5# 纯 CSS 实现24小时超市
  • 适配mpvue平台的的微信小程序日历组件mpvue-calendar
  • 微信小程序开发问题汇总
  • 无服务器化是企业 IT 架构的未来吗?
  • 一份游戏开发学习路线
  • 正则与JS中的正则
  • Semaphore
  • 国内开源镜像站点
  • #传输# #传输数据判断#
  • %@ page import=%的用法
  • (2)空速传感器
  • (4)logging(日志模块)
  • (7)摄像机和云台
  • (ctrl.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MDd_DynamicDebug”不匹配值“
  • (done) NLP “bag-of-words“ 方法 (带有二元分类和多元分类两个例子)词袋模型、BoW
  • (echarts)echarts使用时重新加载数据之前的数据存留在图上的问题
  • (el-Transfer)操作(不使用 ts):Element-plus 中 Select 组件动态设置 options 值需求的解决过程
  • (附源码)springboot 校园学生兼职系统 毕业设计 742122
  • (免费分享)基于springboot,vue疗养中心管理系统
  • (排序详解之 堆排序)
  • (十五)Flask覆写wsgi_app函数实现自定义中间件
  • (最简单,详细,直接上手)uniapp/vue中英文多语言切换
  • *算法训练(leetcode)第四十五天 | 101. 孤岛的总面积、102. 沉没孤岛、103. 水流问题、104. 建造最大岛屿
  • .net 7和core版 SignalR
  • .NET Core WebAPI中使用Log4net 日志级别分类并记录到数据库
  • .NET I/O 学习笔记:对文件和目录进行解压缩操作
  • .NET 除了用 Task 之外,如何自己写一个可以 await 的对象?