Cursor 操作 → Room DAO

Cursor 操作 → Room DAO

老写法(Java + Cursor)

java 复制代码
// 查询
Cursor cursor = db.rawQuery("SELECT * FROM item", null);
List<Item> items = new ArrayList<>();
while (cursor.moveToNext()) {
    long id = cursor.getLong(cursor.getColumnIndex("id"));
    String name = cursor.getString(cursor.getColumnIndex("name"));
    double price = cursor.getDouble(cursor.getColumnIndex("price"));
    items.add(new Item(id, name, price));
}
cursor.close();

// 统计
Cursor countCursor = db.rawQuery("SELECT COUNT(*) FROM item", null);
countCursor.moveToFirst();
int count = countCursor.getInt(0);
countCursor.close();

// 分页
Cursor pageCursor = db.rawQuery(
        "SELECT * FROM item LIMIT ? OFFSET ?",
        new String[]{String.valueOf(20), String.valueOf(offset)});
// ...遍历、关闭

问题在哪里

getColumnIndex 依赖字符串,字段名写错返回 -1,然后 getString(-1) 直接崩。每个查询都要手动遍历 Cursor、手动 close(),忘关就泄漏。LIMIT ? OFFSET ? 这种 SQL 拼接容易出错且可读性差。

新写法(Room DAO)

kotlin 复制代码
@Dao
interface ItemDao {
    // 基本查询
    @Query("SELECT * FROM item")
    suspend fun getAll(): List<Item>

    // 按条件查询
    @Query("SELECT * FROM item WHERE price > :minPrice")
    suspend fun getByPrice(minPrice: Double): List<Item>

    // 统计
    @Query("SELECT COUNT(*) FROM item")
    suspend fun count(): Int

    // 分页 --- 用 PagingSource
    @Query("SELECT * FROM item ORDER BY id ASC")
    fun pagingSource(): PagingSource<Int, Item>

    // 返回 Flow 自动监听数据变化
    @Query("SELECT * FROM item ORDER BY name ASC")
    fun getAllFlow(): Flow<List<Item>>
}

使用:

kotlin 复制代码
// 普通查询
viewModelScope.launch(Dispatchers.IO) {
    val items = db.itemDao().getAll()
    val count = db.itemDao().count()
}

// Flow 自动更新
db.itemDao().getAllFlow()
        .asLiveData()
        .observe(viewLifecycleOwner) { items -> adapter.submitList(items) }

一句话注意

Room 的 @Query 在编译期验证 SQL 语法,表名或字段名写错了编译直接报错。这是 Room 相对手写 Cursor 最大的安全优势。

返回类型为 Flow 的查询,Room 会在数据变更时自动重新发出查询结果。底层是通过数据库的触发器实现的,不是轮询,所以不浪费性能。但注意 Flow 查询不支持 suspend,这两个互斥------要么一次性返回用 suspend,要么持续监听用 Flow

cursor.getColumnIndex() 的失败模式是静默的(返回 -1),而 Room 的错误是编译期的,这也是迁移到 Room 最实在的好处。


Java Android 老项目迁移系列,持续更新中。

相关推荐
周杰伦fans10 分钟前
数列极限的定义
java·开发语言
小白的后端世界22 分钟前
LangChain 模型初始化参数详解:从基础配置到企业级实践
java·人工智能·langchain
广州浮点FLOATLIC29 分钟前
Mentor Graphics浮动许可证管理为什么一到流片节点就失控
java·大数据·数据库·许可证管理·cad 许可证优化
Loongproxy1 小时前
大规模采集为啥用隧道代理IP?会话保持如何做到无感轮换
java·服务器·网络
杰克尼1 小时前
天机学堂面试题
java
Web极客码1 小时前
用 Python 搭建工具调用 Agent 的调试过程
java·服务器·前端
小王C语言1 小时前
MySQL 数据类型:数值类型、字符串类型、日期和时间类型、enum 和 set、find_in_set 查询
android·数据库·mysql
童槿顏丶1 小时前
Jenkins部署(Docker)
java·docker·jenkins
我命由我123451 小时前
Android 控件 - CardView(快速实现圆角)
android·java·java-ee·kotlin·android studio·android-studio·android runtime
2601_963869951 小时前
【计算机毕业设计】基于Java的潮牌购物网站系统的设计与实现
java·开发语言·课程设计