Ошибка "Null check operator used on a null value" при сохранении формы
Заполняю форму текстом и пытаюсь его отправить на вторую страницу. При выполнении form!.save(); вылетает ошибка "Null check operator used on a null value", помоите решить проблему:
Первая страница form_page.dart
import 'package:flutter/material.dart';
import 'package:test_form_example/models/model_user.dart';
import 'package:test_form_example/pages/profile.dart';
class FormPage extends StatefulWidget {
const FormPage({Key? key}) : super(key: key);
@override
_FormPageState createState() => _FormPageState();
}
class _FormPageState extends State<FormPage> {
final _formKey = GlobalKey<FormState>();
User modelUser = User();
@override
Widget build(BuildContext context) {
return Container(
child: Form(
child: ListView(
children: [
TextFormField(
onSaved: (value) => modelUser.name = value!,
),
ElevatedButton(onPressed: _formSave, child: Text('Отправить'))
],
)),
);
}
void _formSave() {
final form = _formKey.currentState;
form!.save();
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => Profile(userInfo: modelUser)));
}
}
Вторая страница profile.dart
import 'package:flutter/material.dart';
import 'package:test_form_example/models/model_user.dart';
class Profile extends StatelessWidget {
final User userInfo;
Profile({required this.userInfo});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Profile'),
),
body: Container(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
Text('Name: ${userInfo.name}'),
],
),
),
);
}
}
Модель model_user.dart
class User{
late String name;
}
Ошибка:
======== Exception caught by gesture ===============================================================
The following _CastError was thrown while handling a gesture:
Null check operator used on a null value
When the exception was thrown, this was the stack:
#0 _FormPageState._formSave (package:test_form_example/pages/form_page.dart:34:9)
#1 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:989:21)
#2 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:198:24)
#3 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:608:11)
#4 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:296:5)
#5 BaseTapGestureRecognizer.acceptGesture (package:flutter/src/gestures/tap.dart:267:7)
#6 GestureArenaManager.sweep (package:flutter/src/gestures/arena.dart:157:27)
#7 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:444:20)
#8 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:420:22)
#9 RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:278:11)
#10 GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:374:7)
#11 GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:338:5)
#12 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:296:7)
#13 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:279:7)
#17 _invoke1 (dart:ui/hooks.dart:185:10)
#18 PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:293:7)
#19 _dispatchPointerDataPacket (dart:ui/hooks.dart:98:31)
(elided 3 frames from dart:async)
Handler: "onTap"
Recognizer: TapGestureRecognizer#c21f5
debugOwner: GestureDetector
state: ready
won arena
finalPosition: Offset(128.0, 142.6)
finalLocalPosition: Offset(128.0, 8.6)
button: 1
sent tap down
====================================================================================================
Ответы (1 шт):
Давайте разберём такой маленький кусочек кода, который на первый взгляд не может сломаться.
final _formKey = GlobalKey<FormState>();
final form = _formKey.currentState;
form!.save();
Но точно не может сломаться? Давайте добавим детали чтобы разобраться:
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final FormState? form = _formKey.currentState;
form!.save();
Ага, теперь мы видим что form это FormState? т.е. может быть как FormState, так и Null.
Смотрим дальше и видим form!. (если конкретнее !) это bang operator он означает, что мы игнорируем анализатор кода и точно уверены что в переменной не будет null. Если это не так, то во время выполнения программы мы поймаем ошибку Null check operator used on a null value что означает что мы пытаемся использовать у переменной значение которое равно null какой-то метод.
Что-же нужно сделать, чтобы исправить данную проблему? Естественно проверить переменную на null:
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final FormState? form = _formKey.currentState;
if(form != null) {
form!.save();
}
Или краткая запись:
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final FormState? form = _formKey.currentState;
form?.save();
Подытожим, использовать bang operator (!) крайне опасное дело, особенно в руках новичка. И давайте не будем забывать, что Null Safety появился чтобы избавиться от ошибки на миллион.
И на подлесок, у вас form равен null из-за того что вы не присвоили _formKey никакому виджету...