Flutter注册表单无法提交至Firebase认证,Provider断言失败求助
Flutter注册表单提交Firebase认证失败及Provider断言错误修复
问题说明
我是Flutter新手,开发移动应用时遇到两个问题:注册表单无法将数据提交到Firebase认证,同时触发Provider断言失败错误。
Auth类代码
class Auth with ChangeNotifier { late String _token; late DateTime _expirytDate; late String _userId; Future<void> signup(String email, String password) async { const url = 'https://identitytoolkit.googleapis.com/v1/accounts:signInWithCustomToken?key=AIzaSyDL5WN64rhcYbYbiLutVA33Ekjixj0M3BE'; final response = await http.post(Uri.parse(url), body: json.encode({ 'email': email, 'password': password, 'returnSecureToken': true, })); } }
AuthCard类代码
class AuthCard extends StatefulWidget { @override _AuthCardState createState() => _AuthCardState(); } class _AuthCardState extends State<AuthCard> { final GlobalKey<FormState> _formKey = GlobalKey(); AuthMode _authMode = AuthMode.Login; Map<String, String> _authData = { 'email': '', 'password': '', }; var _isLoading = false; final _passwordController = TextEditingController(); Future<void> _submit() async { if (!_formKey.currentState!.validate()) { // Invalid! return; } _formKey.currentState!.save(); setState(() { _isLoading = true; }); if (_authMode == AuthMode.Login) { // Log user in } else { // Sign user up await Provider.of<Auth>(context).signup(_authData['email']! ,_authData['password']! ); } setState(() { _isLoading = false; }); } void _switchAuthMode() { if (_authMode == AuthMode.Login) { setState(() { _authMode = AuthMode.Signup; }); } else { setState(() { _authMode = AuthMode.Login; }); } } @override Widget build(BuildContext context) { final deviceSize = MediaQuery.of(context).size; return Card( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10.0), ), elevation: 8.0, child: Container( height: _authMode == AuthMode.Signup ? 320 : 260, constraints: BoxConstraints(minHeight: _authMode == AuthMode.Signup ? 320 : 260), width: deviceSize.width * 0.75, padding: EdgeInsets.all(16.0), child: Form( key: _formKey, child: SingleChildScrollView( child: Column( children: <Widget>[ TextFormField( decoration: InputDecoration(labelText: 'E-Mail'), keyboardType: TextInputType.emailAddress, validator: (value) { if (value!.isEmpty || !value.contains('@')) { return 'Invalid email!'; } return null; }, onSaved: (value) { _authData['email'] = value!; }, ), TextFormField( decoration: InputDecoration(labelText: 'Password'), obscureText: true, controller: _passwordController, validator: (value) { if (value!.isEmpty || value.length < 5) { return 'Password is too short!'; } }, onSaved: (value) { _authData['password'] = value!; }, ), if (_authMode == AuthMode.Signup) TextFormField( enabled: _authMode == AuthMode.Signup, decoration: InputDecoration(labelText: 'Confirm Password'), obscureText: true, validator: _authMode == AuthMode.Signup ? (value) { if (value != _passwordController.text) { return 'Passwords do not match!'; } } : null, ), SizedBox( height: 20, ), if (_isLoading) CircularProgressIndicator() else Padding( padding: const EdgeInsets.all(8.0), child: ElevatedButton( child: Text( _authMode == AuthMode.Login ? 'LOGIN' : 'SIGN UP'), onPressed: _submit, ), ), TextButton( child: Padding( padding: EdgeInsets.symmetric(horizontal: 30.0, vertical: 4), child: Text( '${_authMode == AuthMode.Login ? 'SIGNUP' : 'LOGIN'} INSTEAD'), ), onPressed: _switchAuthMode, style: TextButton.styleFrom(primary: Colors.amber), ), ], ), ), ), ), ); } }
触发的错误信息
Error: Assertion failed: file:///C:/Users/DELL/development/SDK/flutter/.pub-cache/hosted/pub.dartlang.org/provider-6.0.3/lib/src/provider.dart:274:7 C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 266:49 throw_ C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 29:3 assertFailed packages/provider/src/provider.dart 276:11 of packages/flutter_application_1/screens/auth_screen.dart 114:40 _submit C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 84:54 runBody C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 123:5 _async packages/flutter_application_1/screens/auth_screen.dart 101:23 [_submit] packages/flutter/src/material/ink_well.dart 1072:21 handleTap packages/flutter/src/gestures/recognizer.dart 253:24 invokeCallback packages/flutter/src/gestures/tap.dart 627:11 handleTapUp packages/flutter/src/gestures/tap.dart 306:5 [_checkUp] packages/flutter/src/gestures/tap.dart 239:7 handlePrimaryPointer packages/flutter/src/gestures/recognizer.dart 615:9 handleEvent packages/flutter/src/gestures/pointer_router.dart 98:12 [_dispatch] packages/flutter/src/gestures/pointer_router.dart 143:9 <fn> C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/linked_hash_map.dart 21:13 forEach packages/flutter/src/gestures/pointer_router.dart 141:17 [_dispatchEventToRoutes] packages/flutter/src/gestures/pointer_router.dart 127:7 route packages/flutter/src/gestures/binding.dart 460:19 handleEvent packages/flutter/src/gestures/binding.dart 440:14 dispatchEvent packages/flutter/src/rendering/binding.dart 337:11 dispatchEvent packages/flutter/src/gestures/binding.dart 395:7 [_handlePointerEventImmediately] packages/flutter/src/gestures/binding.dart 357:5 handlePointerEvent packages/flutter/src/gestures/binding.dart 314:7 [_flushPointerEventQueue] packages/flutter/src/gestures/binding.dart 295:7 [_handlePointerDataPacket] C:/b/s/w/ir/cache/builder/src/out/host_debug/flutter_web_sdk/lib/_engine/engine/platform_dispatcher.dart 1183:13 invoke1
解决方案
1. 修复Provider断言失败错误
Provider断言失败的核心原因是Widget树中没有上层提供Auth实例,且异步调用时未关闭监听。按以下步骤修改:
- 在App根组件(比如MaterialApp外层)添加
ChangeNotifierProvider,确保Auth实例能被子组件访问:void main() { runApp( ChangeNotifierProvider( create: (ctx) => Auth(), child: MyApp(), ), ); } - 在
_submit方法中调用Provider时,添加listen: false(仅调用方法无需监听状态变化):await Provider.of<Auth>(context, listen: false).signup(_authData['email']!, _authData['password']!);
2. 修复Firebase认证提交失败问题
当前Auth类使用的Firebase接口错误,注册需使用用户创建接口而非自定义令牌登录接口:
- 将signup方法中的URL替换为注册接口:
const url = 'https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=AIzaSyDL5WN64rhcYbYbiLutVA33Ekjixj0M3BE'; - 添加响应错误处理,避免静默失败:
final responseData = json.decode(response.body); if (response.statusCode >= 400) { throw Exception(responseData['error']['message']); } else { _token = responseData['idToken']; _userId = responseData['localId']; _expirytDate = DateTime.now().add( Duration(seconds: int.parse(responseData['expiresIn'])), ); notifyListeners(); }
内容的提问来源于stack exchange,提问作者LeThanhDat
相关产品推荐
相关产品推荐

