Flutter启动时向SQLite表初始化写入固定常量数据实现方法
Flutter 启动自动初始化数据库预置数据实现方案
前置修复(必做,否则数据插入/查询会失败)
你现有代码存在2处字段不匹配问题,先修正:
- 修复
specializeArea表建表语句,给id列添加主键约束,避免重复插入同id数据
找到DbHelper.dart里的_onCreate方法中创建specializeArea表的代码,替换为:await db.execute("CREATE TABLE $Table_specializeArea (" " $C_UserID INTEGER PRIMARY KEY, " " $C_Area TEXT )"); - 修复
specializeModel.dart的字段映射,和数据库列名对齐
把toMap、fromMap方法里的user_areakey改成和数据库列一致的area:Map<String, dynamic> toMap() { var map = <String, dynamic>{ 'id': user_id, 'area': user_area, }; return map; } specializeModel.fromMap(Map<String, dynamic> map) { user_id = map['id']; user_area = map['area']; }
如果是开发调试阶段,修改完建表语句后建议先卸载旧应用重装,避免旧库表结构不匹配报错。
核心实现:预置数据自动写入逻辑
1. 在DbHelper中添加预置数据插入方法
该方法会先判断specializeArea表是否已有数据,无数据才写入,避免每次启动重复插入冗余数据:
// 插入预置专业领域数据 Future<void> _insertPresetSpecializeArea() async { var dbClient = await db; // 先查表内数据量 var countRes = await dbClient.rawQuery("SELECT COUNT(*) as count FROM $Table_specializeArea"); int count = Sqflite.firstIntValue(countRes); // 已有数据直接返回,不重复插入 if (count > 0) return; // 这里替换成你需要的5组预置数据,id不要重复 List<specializeModel> presetAreas = [ specializeModel("1", "计算机科学与技术"), specializeModel("2", "电子信息工程"), specializeModel("3", "生物医学工程"), specializeModel("4", "材料科学与工程"), specializeModel("5", "机械工程"), ]; // 批量插入,使用事务提升插入效率 await dbClient.transaction((txn) async { for (var area in presetAreas) { await txn.insert(Table_specializeArea, area.toMap()); } }); }
2. 修改数据库初始化逻辑,启动时自动触发预置数据写入
找到DbHelper里的initDb方法,在openDatabase完成后调用上面的预置插入方法:
initDb() async { io.Directory documentsDirectory = await getApplicationDocumentsDirectory(); String path = join(documentsDirectory.path, DB_Name); var db = await openDatabase(path, version: Version, onCreate: _onCreate); // 库初始化完成后检查并写入预置数据 await _insertPresetSpecializeArea(); return db; }
这个逻辑不管是首次安装创建数据库,还是后续冷启动打开已有数据库,都会校验预置数据是否存在,不会出现重复插入问题,也不需要每次启动都删表重写。
扩展:预置数据查询(方便后续渲染交互按钮)
在DbHelper中添加查询所有专业领域数据的方法,供页面调用:
// 查询所有预置专业领域数据 Future<List<specializeModel>> getAllSpecializeAreas() async { var dbClient = await db; var res = await dbClient.query(Table_specializeArea); return res.map((e) => specializeModel.fromMap(e)).toList(); }
页面调用示例
在HomeForm的initState里调用查询方法,拿到数据后就可以渲染成按钮组件:
// 新增状态变量存储领域列表 List<specializeModel> areaList = []; @override void initState() { super.initState(); getUserData(); dbHelper = DbHelper(); // 初始化时加载预置领域数据 loadAreaData(); } Future<void> loadAreaData() async { List<specializeModel> list = await dbHelper.getAllSpecializeAreas(); setState(() { areaList = list; }); }
后续在build方法里,你之前预留的//Specialization area注释位置,用ListView或者Wrap组件遍历areaList渲染按钮即可。
内容的提问来源于stack exchange,提问作者Zero
相关产品推荐
相关产品推荐

