如何解决Dart 3.0.5中SQLite保存数据时的空检查运算符异常
问题
我已将现有项目迁移至Dart 3.0.5,起初通过添加?和!解决了空安全问题,应用可正常运行。但现在在SQLite中保存数据时,会抛出运行时错误Null check operator used on a null value,尝试使用??运算符也报错,相关核心代码如下:
Future _onSubmit() async { try { int _result = 0; if (_formKey.currentState!.validate()) { if (_isSupplier == false && _isCustomer == false) { showToast(global.appLocaleValues!['vel_select_ac_type']); } else { setState(() {}); if (_isCustomer == true && _isSupplier == false) { _accountType = 'Customer'; } else if (_isCustomer == false && _isSupplier == true) { _accountType = 'Supplier'; } else if (_isCustomer == true && _isSupplier == true) { _accountType = ',Customer,Supplier,'; } account!.accountType = _accountType!; account!.firstName = _cFirstName.text.trim(); account!.lastName = _cLastName.text.trim(); account!.middleName = _cMiddleName.text.trim(); account!.mobile = _cMobile.text.trim(); account!.phone = _cPhone.text.trim(); account!.email = _cEmail.text.trim(); if (_birthDate != null) { account!.birthdate = DateTime.parse(_birthDate!); } if (_anniversary != null) { account!.anniversary = DateTime.parse(_anniversary!); } account!.gender = _gender!; account!.imagePath = _photopath!; account!.addressLine1 = _cAddressLine1.text.trim(); account!.addressLine2 = _cAddressLine2.text.trim(); account!.city = _cCity.text.trim(); account!.state = _cState.text.trim(); account!.country = _cCountry.text.trim(); account!.namePrefix = _cNamePrefix.text.trim(); account!.nameSuffix = _cNameSuffix.text.trim(); account!.businessName = _cBusinessName.text.trim(); account!.gstNo = _cGstNo.text.trim(); if (_cPincode.text.isNotEmpty) { account!.pincode = int.parse(_cPincode.text.trim()); } account!.isActive = _isActive!; account!.isDelete = false; print('${account!.accountType}'); print('${account!.accountCode}'); if (account!.id == null) { // add account _result = (await dbHelper.accountInsert(account!))!; account!.id = _result; } else { // update account _result = (await dbHelper.accountUpdate(account!))!; AccountSearch accountSearch = AccountSearch(); Navigator.of(context).pushReplacement(MaterialPageRoute( builder: (BuildContext context) => AccountScreen( redirectToCustomersTab: (isAddAsCustomer) ? true : false, a: widget.analytics, o: widget.observer, accountSearch: accountSearch, ))); } if (_result > 0) { int notificationId = int.parse( global.moduleIds['Account'].toString() + '01' + account!.id.toString()); if (account!.birthdate != null && account!.anniversary != null && account!.birthdate!.month == account!.anniversary!.month && account!.birthdate!.day == account!.anniversary!.day && (_oldBirthday != account!.birthdate || _oldAnniversary != account!.anniversary)) { await br.scheduleNotification( notificationId, br .getNextEventDate(account!.birthdate!) .add(Duration(hours: tod.hour, minutes: tod.minute)), '${br.generateAccountName(account!)}\'s Birthday & Anniversary', 'on ${DateFormat('MMMM dd').format(account!.birthdate!)}', '{"module":"Account","id":"${account!.id}"}', setNextDate: true); } else { if (account!.birthdate != null && _oldBirthday != account!.birthdate) { int notificationId = int.parse( global.moduleIds['Account'].toString() + '02' + account!.id.toString()); await br.scheduleNotification( notificationId, br .getNextEventDate(account!.birthdate!) .add(Duration(hours: tod.hour, minutes: tod.minute)), '${br.generateAccountName(account!)}\'s Birthday', 'on ${DateFormat('MMMM dd').format(account!.birthdate!)}', '{"module":"Account","id":"${account!.id}"}', setNextDate: true); } if (account!.anniversary != null && _oldAnniversary != account!.anniversary) { int notificationId = int.parse( global.moduleIds['Account'].toString() + '03' + account!.id.toString()); await br.scheduleNotification( notificationId, br .getNextEventDate(account!.anniversary!) .add(Duration(hours: tod.hour, minutes: tod.minute)), '${br.generateAccountName(account!)}\'s Anniversary', 'on ${DateFormat('MMMM dd').format(account!.anniversary!)}', '{"module":"Account","id":"${account!.id}"}', setNextDate: true); } } setState(() {}); if (returnScreenId == 0) { AccountSearch accountSearch = AccountSearch(); Navigator.of(context).pushReplacement(MaterialPageRoute( builder: (BuildContext context) => AccountScreen( a: widget.analytics, o: widget.observer, accountSearch: accountSearch, redirectToCustomersTab: (isAddAsCustomer) ? true : false, ))); } else if (returnScreenId == 1) { Navigator.of(context).pop(account); } } } } else { _autovalidate = true; setState(() {}); } } catch (e) { print('Exception - accountAddScreen.dart - _onSubmit(): ' + e.toString()); } }
解决方案
错误根源是代码中滥用!强制解包null值,以下是针对性修复方案:
确保
account实例已初始化:
如果是新增账号场景,提前实例化Account对象(比如account = Account();),避免account为null时使用account!触发错误。修复
_accountType的空值问题:
给_accountType设置默认值兜底,避免意外null:String _accountType = ''; // 原有赋值逻辑... account!.accountType = _accountType; // 无需再加!处理用户可选字段的null值:
对于_gender、_photopath、_isActive这类用户可能未设置的字段,用??设置合理默认值,而非强制解包:account!.gender = _gender ?? 'Unknown'; account!.imagePath = _photopath ?? ''; account!.isActive = _isActive ?? true;安全处理数据库操作返回值:
数据库插入/更新可能返回null(比如操作失败),先判断再赋值:// 新增账号时 var insertResult = await dbHelper.accountInsert(account!); if (insertResult != null) { _result = insertResult; account!.id = _result; } else { // 提示用户插入失败 } // 更新账号时 var updateResult = await dbHelper.accountUpdate(account!); if (updateResult != null) { _result = updateResult; } else { // 提示用户更新失败 }修复国际化文本的空值问题:
用??设置默认提示,避免global.appLocaleValues为null时触发错误:showToast(global.appLocaleValues?['vel_select_ac_type'] ?? '请选择账户类型');安全生成notificationId:
确保global.moduleIds['Account']不为null再转换为字符串:String moduleId = global.moduleIds['Account']?.toString() ?? '0'; int notificationId = int.parse(moduleId + '01' + account!.id.toString());
内容的提问来源于stack exchange,提问作者syed moiz
相关产品推荐
相关产品推荐

