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 老项目迁移系列,持续更新中。

相关推荐
Joy T18 分钟前
Agent 确定性上下文设计:从 Prompt 参数注入到能力分层
java·开发语言·微服务·架构·prompt·agent context
m0_587383003 小时前
广州 24 小时自助健身房解决方案技术实现与实战指南
java·spring·小程序·架构·需求分析
·云扬·4 小时前
Prompt 工程与安全:从 System 设计到注入防御
java·人工智能·安全·ai·prompt
代码不停4 小时前
自动化测试(java)
java·开发语言·selenium·自动化
鬼手点金6 小时前
opencode-rules 插件
java·开发语言·前端·人工智能·chrome·git·github
paopaokaka_luck7 小时前
滑雪场管理系统(AI智能助手流式对话,ECharts 运营数据分析、教练、雪具与场地一体化预约,钱包支付退款、订单核销与服务评价)
java·人工智能·spring boot·网络协议·数据分析·echarts
Wang's Blog8 小时前
Java 项目实战: 交友项目 - Dubbo 的内部结构与一次调用的完整链路
java·dubbo
geovindu8 小时前
sql:Search-Optimized SQL Queries using mysql 9.0
android·数据库·sql·mysql·数据库开发·数据库架构
Wang's Blog8 小时前
Java 项目实战: 交友项目 - Dubbo 入门引导
java·dubbo·交友
蜗牛互联网8 小时前
Python Agent工具调用的白名单、参数校验与审批门禁
java·服务器·前端·人工智能·后端·python