Flutter数据库助手类报错:非空变量'_db'需初始化
解决Flutter DbHelper中非空变量'_db'未初始化的错误
错误核心原因是Dart的空安全机制:你声明的static Database _db;是非空变量,但没有赋予初始值,而空安全要求所有非空变量必须在声明时或构造函数中完成初始化。
直接解决方案
将_db的声明改为可空类型:
static Database? _db;
这样就允许_db初始为null,和你在db getter中延迟初始化的逻辑完全匹配。
修改后的完整DbHelper代码
import 'package:fitness_app/Login/login_data.dart'; import 'package:fitness_app/user.dart'; import 'package:path/path.dart'; import 'package:path_provider/path_provider.dart'; import 'package:sqflite/sqflite.dart'; import 'dart:io' as io; class DbHelper { // 修改:声明为可空类型 static Database? _db; static const String DB_Name = 'test.db'; static const String Table_User = 'user'; static const int Version = 1; static const String C_UserID = 'user_id'; static const String C_UserName = 'user_name'; static const String C_Email = 'email'; static const String C_Password = 'password'; Future<Database> get db async { // 非空断言:确认_db不为空时使用 if (_db != null) { return _db!; } _db = await initDb(); return _db!; } initDb() async { io.Directory documentsDirectory = await getApplicationDocumentsDirectory(); String path = join(documentsDirectory.path, DB_Name); var db = await openDatabase(path, version: Version, onCreate: _onCreate); return db; } _onCreate(Database db, int intVersion) async { await db.execute("CREATE TABLE $Table_User (" " $C_UserID TEXT, " " $C_UserName TEXT, " " $C_Email TEXT," " $C_Password TEXT, " " PRIMARY KEY ($C_UserID)" ")"); } Future<int> saveData(UserModel user) async { var dbClient = await db; var res = await dbClient.insert(Table_User, user.toMap()); return res; } Future<UserModel?> getLoginUser(String userId, String password) async { var dbClient = await db; // 优化:改用参数化查询,避免SQL注入风险 var res = await dbClient.query( Table_User, where: "$C_UserID = ? AND $C_Password = ?", whereArgs: [userId, password] ); if (res.length > 0) { return UserModel.fromMap(res.first); } return null; } Future<int> updateUser(UserModel user) async { var dbClient = await db; var res = await dbClient.update(Table_User, user.toMap(), where: '$C_UserID = ?', whereArgs: [user.user_id]); return res; } Future<int> deleteUser(String user_id) async { var dbClient = await db; var res = await dbClient .delete(Table_User, where: '$C_UserID = ?', whereArgs: [user_id]); return res; } }
补充说明
- 在
dbgetter中,当确认_db不为null时,使用_db!做非空断言——因为initDb返回的是Future<Database>(非空类型),所以赋值后的_db必然是非空的。 - 额外优化了
getLoginUser的查询方式:避免直接字符串拼接SQL参数,改用参数化查询,这是数据库操作的安全最佳实践,可有效防止SQL注入风险。
内容的提问来源于stack exchange,提问作者nur wyna
相关产品推荐
相关产品推荐

