You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter集成Sqflite实现注册登录点击注册无响应问题求助

问题说明

基于Sqflite开发Flutter应用注册/登录数据库模块时,点击注册按钮无响应。开发者有MySQL使用经验,正在学习Flutter与Sqflite技术栈,附数据库实现、注册逻辑代码如下,排查问题。

原有数据库实现代码

class DbHelper {
  static const String DB_Name = 'test.db';
  static const String Table_User = 'user';
  static const int Version = 1;
  static const String _Email = 'email';
  static const String _Password = 'password';
  static const String _Name = 'name';
  
  static Database? _db;
  Future<Database?> get db async {
    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 ("
      "$_Email TEXT ,"
      "$_Password TEXT ," 
      "$_Name TEXT ,"
      " PRIMARY KEY ($_Email)"
      " )");
  }

  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 email, String password) async {
    var dbClient = await db;
    var res = await dbClient!.rawQuery("SELECT * FROM $Table_User WHERE "
        "$_Email = '$email' AND "
        "$_Password = '$password'");

    if (res.length > 0) {
      return UserModel.fromMap(res.first);
    }
    return null;
  }
}

原有注册功能代码

signUp() async {
  final form = _formKey.currentState;
  String uEmail = _Email.text;
  String password = _Password.text;
  String cpassword = _CPassword.text;
  String uname = _Name.text;

  if(form != null && !form.validate ()){
    if (password != cpassword) {
      alertDialog(context, "Password Mismatch");
    }
    else{
      _formKey.currentState?.save();
      UserModel uModel = UserModel(uEmail, password, uname);
      await dbHelper.insert(uModel).then((userData) {
        alertDialog(context, "Success");
        Navigator.push(context, MaterialPageRoute(builder: (_) => LoginForm()));
      }).catchError((error){
        print(error);
        alertDialog(context, "Error: Data Save Fail");
      });
    }
  }
}
问题根因

一共3个直接导致功能异常的bug,1个安全隐患:

  • 表单校验逻辑写反:判断条件用了!form.validate(),只有表单校验不通过时才会进入后续注册流程,表单正常填完符合校验规则时,整个逻辑块完全不执行,这是点击按钮无响应的核心原因
  • 方法调用不匹配:DbHelper中定义的插入方法名为saveData(),注册逻辑中调用的是不存在的dbHelper.insert(),就算表单逻辑正常,这里也会直接抛方法不存在的异常
  • 业务逻辑位置错误:两次密码输入一致性校验被放在「表单校验不通过」的分支中,正常注册流程完全不会校验两次密码是否相同
  • SQL拼接风险:登录查询直接用字符串拼接参数,容易出现特殊字符转义失败、SQL注入问题
修复方案

修正注册逻辑

把表单判断条件改对,调整密码校验位置,调用正确的插入方法,修正后代码如下:

signUp() async {
  final form = _formKey.currentState;
  // 取输入值时去掉首尾空格,避免误输入空格导致异常
  String uEmail = _Email.text.trim();
  String password = _Password.text.trim();
  String cpassword = _CPassword.text.trim();
  String uname = _Name.text.trim();

  // 表单存在且校验通过时才走注册流程
  if(form != null && form.validate()){
    // 先校验两次密码是否一致
    if (password != cpassword) {
      alertDialog(context, "Password Mismatch");
      return;
    }
    _formKey.currentState?.save();

    UserModel uModel = UserModel(uEmail, password, uname);
    // 调用DbHelper中实际存在的saveData方法
    await dbHelper.saveData(uModel).then((userData) {
      alertDialog(context, "Success");
      Navigator.push(context, MaterialPageRoute(builder: (_) => LoginForm()));
    }).catchError((error){
      print(error);
      alertDialog(context, "Error: Data Save Fail");
    });
  }
}

优化数据库查询逻辑

把登录的SQL查询改成参数化形式,避免转义和注入问题:

Future<UserModel?> getLoginUser(String email, String password) async {
  var dbClient = await db;
  // 用?作为参数占位符,参数通过arguments数组传递,sqflite会自动处理转义
  var res = await dbClient!.rawQuery(
    "SELECT * FROM $Table_User WHERE $_Email = ? AND $_Password = ?",
    [email.trim(), password.trim()]
  );

  if (res.isNotEmpty) {
    return UserModel.fromMap(res.first);
  }
  return null;
}
额外优化建议
  • 因为表结构中设置email为主键,插入重复邮箱会直接抛异常,注册前可以先查询邮箱是否已经存在,提前给用户提示
  • 不要明文存储密码,建议对密码做哈希处理(比如用bcrypt)后再存入数据库,提升安全性
  • 初始化数据库、插入数据的逻辑中可以加打印日志,方便后续调试时快速定位问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 06:21:31