Flutter使用SQFlite查询收藏数据报Null转String类型转换错误
问题原因
- 本地残留脏数据:当前查询返回的记录中
name字段值为Model,与你定义的测试数据name值Test完全不符,说明这条id=1的记录是前期调试时插入的无效数据:当时要么Model类还未定义imagePath、description字段,要么插入逻辑有问题,导致这两个字段存入了null值。你配置了ConflictAlgorithm.replace冲突规则,但后续没有传入正确的id=1完整数据执行插入,这条空值记录就一直残留在库中。 - 空值强转触发崩溃:从数据库取数转Model的逻辑直接用
as String强转字段值,没有做null兼容,只要查询结果里存在空值就会抛出_CastError类型转换异常。 - 潜在逻辑风险:如果调用
initDb()时没有加await等待初始化完成就执行插入/查询,或者修改表结构后没有升级数据库版本、没有清理旧库,也会出现字段不存在、查询值为null的问题。
修复方案
- 清理旧库重置状态:调试阶段直接卸载应用后重新运行,会删除本地残留的错误数据库文件,触发
onCreate回调重新创建包含所有字段的完整表。如果是已上线版本,需要递增数据库版本号,在onUpgrade回调中补全缺失字段、清理无效脏数据,不能依赖用户卸载重装。 - 校准数据写入流程:所有数据库操作必须在
await initDb()执行完成后再调用,初始化完成后调用insertEntry传入你定义的完整测试Model实例,插入前可以打印model.toMap()的输出,确认四个字段的值都符合预期、非空。 - 增加空值兜底逻辑:修改查询转换代码,对可能返回null的字段加默认值兜底,从根源避免强转崩溃,参考实现如下:
Future<List<Model>> getMechanism() async { final Database db = await database; final List<Map<String, dynamic>> maps = await db.query('fav'); return List.generate(maps.length, (i) { final row = maps[i]; return Model( id: row['id'] as int, name: (row['name'] as String?) ?? '', imagePath: (row['imagePath'] as String?) ?? '', description: (row['description'] as String?) ?? '', ); }); }
- 可选优化:根据业务规则调整Model类的字段定义,允许为空的字段设置为可空类型,不允许为空的字段在写入、读取层统一做默认值校验,避免其他位置遗漏空判断触发异常。
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

