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

ROOM 数据库 | 实现自定义 ContentProvider 插入数据

代码目标

  • insert()/bulkInsert() 分别完成单条和多条插入。
  • 数据转换/校验、并发控制、数据库事务、协程切换等操作严谨
  • 插入后通知外界内容变化,便于观测或数据同步。
  • 自动维护数据库容量,避免记录爆炸增长。

疑问

当Dao 定义 insert 添加了 suspend,那么直接在 ContentProvider insert 中直接调用这个方法的时候会报错。

//DataDao.kt@Insertsuspend fun insert(data: Data): Long//DataContentProvider.ktdatabase.runInTransaction<Long> {DataDao.insert(data)}

报错提示如下:

Suspension functions can be called only within coroutine body

The 'insertData' suspension point is inside a critical section

解决方案:

删除 suspend。

  • 数据库事务/同步逻辑优先用数据库自身机制,不要人工加同步锁和suspend混用

DEMO

  1. 线程与协程

    • 使用Dispatchers.IO在后台线程执行数据库操作。
    • runBlocking确保阻塞当前线程直到协程完成。
  2. 事务处理

    • runInTransaction保证插入操作的原子性(要么全部成功,要么全部失败)。
  3. 数据一致性

    • 通过synchronized(mLock)防止多线程竞争。
    • 插入后调用notifyChange通知其他组件数据已更新。
  4. 性能优化

    • 批量插入减少数据库操作次数。
    • 自动清理旧数据避免表过大。
    //功能:处理单条记录的插入请求。override fun insert(uri: Uri, values: ContentValues?): Uri? {Log.d(TAG, "insert uri=$uri")values ?: throw IllegalArgumentException("ContentValues cannot be null")return when (sURLMatcher.match(uri)) {SINGLE_RECORD_URI_CODE, MULTIPLE_RECORD_URI_CODE -> {processInsert(uri, values)}    //返回值:插入成功后返回新记录的URI。(因为processInsert的方法是返回URI)else -> throw IllegalArgumentException("Invalid URI, cannot insert with URI: $uri")}}//功能:执行具体的插入逻辑。private fun processInsert(uri: Uri, values: ContentValues?): Uri? {Log.d(TAG, "processInsert() -- uri=$uri")values ?: throw IllegalArgumentException("ContentValues cannot be null")//【数据转换】将 ContentValues 转换成自定义的 Data 对象val data = convertContentValuesToData(values)//【协程与线程】使用 runBlocking 启动协程,在 OI 线程中执行数据库操作val id = runBlocking {withContext(Dispatchers.IO) {synchronized(mLock) {//【事务处理】通过database.runInTransaction确保插入操作的原子性。database.runInTransaction<Long> {dataDao.insertData(data)}}}}// 插入失败(id < 0)应该返回null。val insertUri = ContentUris.withAppendedId(uri, id)//成功时构造新记录的URI,并通过ContentResolver通知数据变化。context?.contentResolver?.notifyChange(uri, null)return insertUri}//功能:将ContentValues转换为自定义的Data对象。//其中Constants.GET_FEATURE_FAIL_INT是预定义的常量private fun convertContentValuesToData(values: ContentValues): Data {return Data(netId= values.getAsLong(DataContract.DataColumns.netId)?: Constants.GET_FEATURE_FAIL_INT.toLong(),rat = values.getAsFloat(DataContract.DataColumns.rat)?: Constants.GET_FEATURE_FAIL_INT.toFloat(),ratType = values.getAsString(DataContract.DataColumns.ratType)?: Constants.GET_FEATURE_FAIL// ...其他字段类似处理)}// 批量插入 start//功能:批量插入多条记录。override fun bulkInsert(uri: Uri, values: Array<ContentValues>): Int {Log.d(TAG, "bulkInsert() -- uri=$uri")return when (sURLMatcher.match(uri)) {MULTIPLE_RECORD_URI_CODE -> performBulkInsert(uri, values)else -> throw IllegalArgumentException("Invalid URI, cannot bulk insert with URI: $uri")}}private fun performBulkInsert(uri: Uri, values: Array<ContentValues>): Int {Log.d(TAG, "performBulkInsert() -- uri=$uri")val dataList = values.map { convertContentValuesToData(it) }val sumInserted = runBlocking {withContext(Dispatchers.IO) {synchronized(mLock) {var insertedCount = 0database.runInTransaction {insertedCount =dataDao.insertRadioList(dataList).size}return@synchronized insertedCount}}}if (numInserted > 0) {context?.contentResolver?.notifyChange(DataContract.CONTENT_URI, null)} else {Log.d(TAG, "bulkInsert: Fail to insert values.")}return sumInserted}

相关介绍

ROOM 数据库接口和代码实现-CSDN博客

http://www.xdnf.cn/news/6212.html

相关文章:

  • 30天通过软考高项-第九天
  • LeetCode 55. 跳跃游戏(中等)
  • 多线程(三)
  • 团结引擎 1.5.0 发布,抖音小游戏平台即将开放、Shader Graph功能新增…引擎能力再提升!
  • 深入探索局域网技术:从理论到实战
  • 如何下载 Microsoft SQL Server Management Studio 2019
  • 最大子段和(就是之前总结线性dp思想)
  • 现代垃圾收集器
  • 公路水运安全员A证备考要点
  • 如何解决电脑蓝屏错误代码:Oxc0000098
  • OSS-承载数据的巨轮
  • 同设备访问php的多个接口会有先后等待问题
  • 基于 art 下的类加载机制,实现函数抽取壳
  • Java—接口和抽象类
  • WordPress 文章和页面:它们的区别是什么?
  • Pomelo知识框架
  • Python爬虫之品牌口碑数据抓取
  • 识别硬盘驱动器的接口类型,及其与计算机连接的方式
  • 碎片笔记|AI生成图像溯源方法源码复现经验(持续更新中……)
  • 解放双手的鼠标自动点击软件
  • R语言学习--Day02--实战经验反馈
  • 基于EFISH-SCB-RK3576/SAIL-RK3576的智慧路灯控制器技术方案
  • 高压开关/断路器机械特性试验的目的及设备
  • [python] python静态方法,类方法,实例方法实现及其区别
  • 【沉浸式求职学习day39】【双指针算法题】
  • 公链开发及其配套设施:钱包与区块链浏览器
  • 【Python】杂乱-[代码]Python 输出/打印列表(list)的方法
  • 三子棋设计
  • C#上位机RS485通信控制变频器
  • 3、ubantu系统docker常用命令