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

相关推荐
智慧物业老杨1 小时前
物业日常巡查的数智化重构:从“打卡式巡检“到“闭环式风控“
android·java·人工智能·系统架构·rxjava
alexhilton7 小时前
藏在设备上的秘密,终究藏不住
android·kotlin·android jetpack
步行cgn8 小时前
Spring c 命名空间注入详解
java·后端·spring
明月_清风8 小时前
Maven 到底是什么?一篇文章搞懂 Java 项目构建与依赖管理
java·后端·maven
aramae8 小时前
MySQL复合查询(8)
java·c语言·开发语言·后端·算法
Rain的Java大神之路9 小时前
如何快速上传10G文件
java·spring boot·redis·后端·mysql·spring cloud·面试
Wang's Blog10 小时前
Java 接入Redis: 通用命令与键管理
java·服务器·redis
Wang's Blog10 小时前
Java 接入Redis: 列表集合与有序集合操作命令
java·服务器·redis
Ivanqhz10 小时前
SVD++算法
java·服务器·网络·深度学习·神经网络
qq_25183645711 小时前
springboot vue3 开发实现 拼豆管理系统
java·开发语言·ai编程