You need to enable JavaScript to run this app. Android SQLite查询封装ArrayList时结果全为最后一行重复
优惠活动
大模型
产品
解决方案
定价
更多

Android SQLite查询封装ArrayList时结果全为最后一行重复

问题根因

你在 getFiles() 方法中只在循环外初始化了一次 FileUploaded 对象,遍历 Cursor 时反复修改同一个对象的属性,再把这个对象的引用反复添加到 ArrayList 里。
Java 的 ArrayList 存储的是对象的内存引用,不是对象本身的深拷贝。最终列表里所有元素都指向同一个内存地址的实体,属性值自然会被最后一次循环读取的行数据覆盖,导致所有返回结果都和最后一行一模一样。

修复代码

把实体对象的实例化逻辑移到循环内部,每读取一行数据就创建一个新的 FileUploaded 实例,再添加到列表即可,修改后的完整查询方法如下:

public ArrayList<FileUploaded> getFiles(){
    SQLiteDatabase db = this.getReadableDatabase();
    ArrayList<FileUploaded> results = new ArrayList<>();
    Cursor cs = db.rawQuery("SELECT * FROM files", null);
    // 直接用moveToNext做循环判断,逻辑更简洁
    while (cs.moveToNext()) {
        // 每一行数据对应一个新的实体实例
        FileUploaded file = new FileUploaded();
        file.setId(cs.getInt(cs.getColumnIndexOrThrow("id")));
        file.setTitle(cs.getString(cs.getColumnIndexOrThrow("title")));
        file.setImage(BitmapUtility.getImage(cs.getBlob(cs.getColumnIndexOrThrow("image"))));
        results.add(file);
    }
    // 关闭Cursor释放数据库资源
    cs.close();
    return results;
}
优化提示
  • 用 getColumnIndexOrThrow() 代替原代码的 getColumnIndex(),如果字段名写错会直接抛出明确的异常,比字段不存在时返回-1的隐形bug更容易排查。
  • 遍历 Cursor 时不需要单独先调用 moveToFirst() 再判断是否到末尾,直接用 moveToNext() 做循环条件可以覆盖空 Cursor、非空 Cursor 的所有场景,逻辑更不容易出错。
  • 操作完成后必须关闭 Cursor,避免数据库连接相关的内存泄漏。

内容的提问来源于stack exchange,提问作者Ahmed Laggoun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.05 03:45:00