Ошибка: После удаления использовался фокус-узел. Как только вы вызвали dispose() для узла фокуса, он больше не может использоваться

#flutter #flutter-web

Вопрос:

Я создал простую веб-страницу, на которой у меня есть две кнопки: одна для добавления донора, а другая для перечисления доноров. При нажатии каждой кнопки я хочу, чтобы открывались соответствующие страницы.

Я нажимаю кнопку «Добавить донора», заполняю форму и нажимаю «Отправить». Затем я нажимаю «Список доноров» и возвращаюсь к «Добавить донора», и при нажатии на поле » Имя » я получаю следующую ошибку при запуске этого в браузере Chrome.

 Error: A FocusNode was used after being disposed.
Once you have called dispose() on a FocusNode, it can no longer be used.
    at Object.throw_ [as throw] (http://localhost:62365/dart_sdk.js:5334:11)
    at http://localhost:62365/packages/flutter/src/foundation/change_notifier.dart.lib.js:83:21
    at focus_manager.FocusNode.new.[_debugAssertNotDisposed] (http://localhost:62365/packages/flutter/src/foundation/change_notifier.dart.lib.js:86:25)
    at focus_manager.FocusNode.new.notifyListeners (http://localhost:62365/packages/flutter/src/foundation/change_notifier.dart.lib.js:113:51)
    at focus_manager.FocusNode.new.[_notify] (http://localhost:62365/packages/flutter/src/widgets/widget_span.dart.lib.js:47534:12)
    at focus_manager.FocusManager.new.[_applyFocusChange] (http://localhost:62365/packages/flutter/src/widgets/widget_span.dart.lib.js:48310:26)
    at Object._microtaskLoop (http://localhost:62365/dart_sdk.js:39176:13)
    at _startMicrotaskLoop (http://localhost:62365/dart_sdk.js:39182:13)
    at http://localhost:62365/dart_sdk.js:34689:9
 

Это мой фрагмент кода

 import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        Navigator.push(
          context,
          MaterialPageRoute(
            builder: (BuildContext context) =>
                BloodDonationPage(),
          ),
        );
      },
      child: Scaffold(
        body: Center(
          child: Container(
            width: 200,
            height: 100,
            child: Card(
              elevation: 20,
              color: Colors.pink[100],
              shape: RoundedRectangleBorder(
                side:
                BorderSide(color: Colors.white70, width: 1),
                borderRadius: BorderRadius.circular(10),
              ),
              margin: EdgeInsets.all(8.0),
              child: Center(
                  child: Text(
                    "Blood Donation",
                    style: TextStyle(
                        fontSize: 20,
                        fontWeight: FontWeight.bold),
                  )),
            ),
          ),
        ),
      ),
    );
  }
}

class BloodDonationPage extends StatefulWidget {
  @override 
  _BloodDonationPageState createState() => _BloodDonationPageState();
}

class _BloodDonationPageState extends State<BloodDonationPage> {

  bool _addButton = false;
  bool _listButton = false;

  @override
  Widget build(BuildContext context) {
    return  Column(
      mainAxisAlignment: MainAxisAlignment.start,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Container(
          height: 60,
          //width: 600,
          child: Card(
            color: Colors.pink[50],
            shadowColor: Colors.pink,
            elevation: 20,
            child: ListView(
              scrollDirection: Axis.horizontal,
              children: [
                GestureDetector(
                  onTap: () {
                    setState(() {
                      _addButton = true;
                      _listButton = false;
                    });
                  },
                  child: Padding(
                    padding: const EdgeInsets.only(left: 60, right: 30.0),
                    child: Card(
                      elevation: 20,
                      color: Colors.pink[100],
                      shape: RoundedRectangleBorder(
                        side:
                        BorderSide(color: Colors.white70, width: 1),
                        borderRadius: BorderRadius.circular(10),
                      ),
                      margin: EdgeInsets.all(8.0),
                      child: Container(
                        padding: EdgeInsets.symmetric(horizontal: 10),
                        child: Center(
                            child: Text(
                              "Add Donor",
                              style: TextStyle(
                                  fontSize: 18,
                                  fontWeight: FontWeight.bold),
                            )),
                      ),
                    ),
                  ),
                ),
                GestureDetector(
                  onTap: () {
                    setState(() {
                      _addButton = false;
                      _listButton = true;
                    });
                  },
                  child: Padding(
                    padding: const EdgeInsets.only(left: 60, right: 30.0),
                    child: Card(
                      elevation: 20,
                      color: Colors.pink[100],
                      shape: RoundedRectangleBorder(
                        side: BorderSide(color: Colors.white70, width: 1),
                        borderRadius: BorderRadius.circular(10),
                      ),
                      margin: EdgeInsets.all(8.0),
                      child: Container(
                        padding: EdgeInsets.symmetric(horizontal: 10),
                        child: Center(
                            child: Text(
                              "List Donors",
                              style: TextStyle(
                                  fontSize: 18, fontWeight: FontWeight.bold),
                            )),
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
        _addButton ? Flexible(child: BloodDonorDetailPage()) : SizedBox.shrink(),
        _listButton ? Flexible(child: ListBloodDonorPage()) : SizedBox.shrink(),
      ],
    );
  }
}

class BloodDonorDetailPage extends StatefulWidget {
  @override
  _BloodDonorDetailPageState createState() => _BloodDonorDetailPageState();
}

class _BloodDonorDetailPageState extends State<BloodDonorDetailPage> {

  final _formKey = GlobalKey<FormBuilderState>();

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(30.0),
      child: FormBuilder(
        autovalidateMode: AutovalidateMode.disabled,
        key: _formKey,
        child: Scaffold(
          body: Column(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: [
                    FormBuilderTextField(
                      autofocus: true,
                      name: 'name',
                      validator: FormBuilderValidators.compose([
                        FormBuilderValidators.required(context),
                        FormBuilderValidators.maxLength(context, 50),
                      ]),
                      decoration: InputDecoration(labelText: 'Name'),
                       ),
                    FormBuilderTextField(
                      name: 'phone',
                      validator: FormBuilderValidators.compose([
                        FormBuilderValidators.required(context),
                        FormBuilderValidators.minLength(context, 10),
                        FormBuilderValidators.maxLength(context, 10),
                        FormBuilderValidators.numeric(context,
                            errorText: 'Mobile No should be 10 digits')
                      ]),
                      keyboardType: TextInputType.number,
                      decoration: InputDecoration(labelText: 'Phone'),
                    ),
                    FormBuilderChoiceChip(
                      name: 'gender',
                      elevation: 10,
                      selectedColor: Colors.white,
                      disabledColor: Colors.black12,
                      alignment: WrapAlignment.spaceAround,
                      options: ['M', 'F']
                          .map((value) => FormBuilderFieldOption(
                        value: value,
                        child: (value == 'M')
                            ? Text('Male')
                            : Text('Female'),
                      ))
                          .toList(),
                      decoration: InputDecoration(labelText: 'Gender'),
                    ),
                    FormBuilderChoiceChip(
                      name: 'bloodGroup',
                      elevation: 10,
                      selectedColor: Colors.white,
                      disabledColor: Colors.black12,
                      alignment: WrapAlignment.spaceAround,
                      options: ['A ','O ']
                          .map((value) => FormBuilderFieldOption(value: value))
                          .toList(),
                      decoration: InputDecoration(labelText: 'Blood Group'),
                    ),
              Expanded(
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    MaterialButton(
                      color: Theme.of(context).accentColor,
                      child: Text('Submit',
                        style: TextStyle(color: Colors.white),
                      ),
                      onPressed: () async {
                        //print(_formKey.currentState.mounted);
                        Map<String, dynamic> _donorMap;
                        if (_formKey.currentState.validate()) {
                          _formKey.currentState.save();
                          //print(_formKey.currentState.value);
                               _donorMap = {
                            ..._formKey.currentState.value,
                            'createdDate': DateTime.now()
                          };
                          print(_donorMap);
                          /*await BloodDonorsController()
                              .saveBloodDonors(widget.mode!, _donorMap);*/
                          ScaffoldMessenger.of(context).showSnackBar(
                            SnackBar(
                              content: Text('Add Donor Successful'),
                            ),
                          );
                          _formKey.currentState.reset();
                          //FocusScope.of(context).requestFocus(focusNode);
                        } else {
                          ScaffoldMessenger.of(context).showSnackBar(
                            SnackBar(
                              content: Text('Validation Failed'),
                            ),
                          );
                        }
                      },
                    ),
                    SizedBox(width: 20),
                    MaterialButton(
                      color: Theme.of(context).accentColor,
                      child: Text(
                        "Reset",
                        style: TextStyle(color: Colors.white),
                      ),
                      onPressed: () {
                        _formKey.currentState.reset();
                      },
                    ),
                  ],
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}


class ListBloodDonorPage extends StatefulWidget {
  @override
  _ListBloodDonorPageState createState() => _ListBloodDonorPageState();
}

class _ListBloodDonorPageState extends State<ListBloodDonorPage> {
  @override
  Widget build(BuildContext context) {
    return Container(child: Text('Display List of Donors'),);
  }
}
 

В чем здесь проблема?
Кто-нибудь может мне помочь, пожалуйста?

Ответ №1:

Я смог, наконец, решить эту проблему, преобразовав виджеты с отслеживанием состояния в методы и добавив виджет Видимость для отображения виджета с сохранением состояния, как показано ниже.

 import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        Navigator.push(
          context,
          MaterialPageRoute(
            builder: (BuildContext context) =>
                BloodDonationPage(),
          ),
        );
      },
      child: Scaffold(
        body: Center(
          child: Container(
            width: 200,
            height: 100,
            child: Card(
              elevation: 20,
              color: Colors.pink[100],
              shape: RoundedRectangleBorder(
                side:
                BorderSide(color: Colors.white70, width: 1),
                borderRadius: BorderRadius.circular(10),
              ),
              margin: EdgeInsets.all(8.0),
              child: Center(
                  child: Text(
                    "Blood Donation",
                    style: TextStyle(
                        fontSize: 20,
                        fontWeight: FontWeight.bold),
                  )),
            ),
          ),
        ),
      ),
    );
  }
}

class BloodDonationPage extends StatefulWidget {
  @override
  _BloodDonationPageState createState() => _BloodDonationPageState();
}

class _BloodDonationPageState extends State<BloodDonationPage> {

  bool _addButton = false;
  bool _listButton = false;
  final _formKey = GlobalKey<FormBuilderState>();

  @override
  Widget build(BuildContext context) {
    return  Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.start,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Container(
            height: 60,
            //width: 600,
            child: Card(
              color: Colors.pink[50],
              shadowColor: Colors.pink,
              elevation: 20,
              child: ListView(
                scrollDirection: Axis.horizontal,
                children: [
                  GestureDetector(
                    onTap: () {
                      setState(() {
                        _addButton = true;
                        _listButton = false;
                      });
                    },
                    child: Padding(
                      padding: const EdgeInsets.only(left: 60, right: 30.0),
                      child: Card(
                        elevation: 20,
                        color: Colors.pink[100],
                        shape: RoundedRectangleBorder(
                          side:
                          BorderSide(color: Colors.white70, width: 1),
                          borderRadius: BorderRadius.circular(10),
                        ),
                        margin: EdgeInsets.all(8.0),
                        child: Container(
                          padding: EdgeInsets.symmetric(horizontal: 10),
                          child: Center(
                              child: Text(
                                "Add Donor",
                                style: TextStyle(
                                    fontSize: 18,
                                    fontWeight: FontWeight.bold),
                              )),
                        ),
                      ),
                    ),
                  ),
                  GestureDetector(
                    onTap: () {
                      setState(() {
                        _addButton = false;
                        _listButton = true;
                      });
                    },
                    child: Padding(
                      padding: const EdgeInsets.only(left: 60, right: 30.0),
                      child: Card(
                        elevation: 20,
                        color: Colors.pink[100],
                        shape: RoundedRectangleBorder(
                          side: BorderSide(color: Colors.white70, width: 1),
                          borderRadius: BorderRadius.circular(10),
                        ),
                        margin: EdgeInsets.all(8.0),
                        child: Container(
                          padding: EdgeInsets.symmetric(horizontal: 10),
                          child: Center(
                              child: Text(
                                "List Donors",
                                style: TextStyle(
                                    fontSize: 18, fontWeight: FontWeight.bold),
                              )),
                        ),
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
          Visibility(visible: _addButton, maintainState: true,child: buildAdd()),
          Visibility(visible: _listButton ,child: buildList()),
        ],
      ),
    );
  }

  Widget buildList() => Container(child: Text('Display List of Donors'),);

  Widget buildAdd() => Padding(
    padding: const EdgeInsets.all(30.0),
    child: Column( children: [ FormBuilder(
      autovalidateMode: AutovalidateMode.disabled,
      key: _formKey,
      child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: [
            FormBuilderTextField(
              autofocus: true,
              name: 'name',
              validator: FormBuilderValidators.compose([
                FormBuilderValidators.required(context),
                FormBuilderValidators.maxLength(context, 50),
              ]),
              decoration: InputDecoration(labelText: 'Name'),
            ),
            FormBuilderTextField(
              name: 'phone',
              validator: FormBuilderValidators.compose([
                FormBuilderValidators.required(context),
                FormBuilderValidators.minLength(context, 10),
                FormBuilderValidators.maxLength(context, 10),
                FormBuilderValidators.numeric(context,
                    errorText: 'Mobile No should be 10 digits')
              ]),
              keyboardType: TextInputType.number,
              decoration: InputDecoration(labelText: 'Phone'),
            ),
            FormBuilderChoiceChip(
              name: 'gender',
              elevation: 10,
              selectedColor: Colors.white,
              disabledColor: Colors.black12,
              alignment: WrapAlignment.spaceAround,
              options: ['M', 'F']
                  .map((value) => FormBuilderFieldOption(
                value: value,
                child: (value == 'M')
                    ? Text('Male')
                    : Text('Female'),
              ))
                  .toList(),
              decoration: InputDecoration(labelText: 'Gender'),
            ),
            FormBuilderChoiceChip(
              name: 'bloodGroup',
              elevation: 10,
              selectedColor: Colors.white,
              disabledColor: Colors.black12,
              alignment: WrapAlignment.spaceAround,
              options: ['A ','O ']
                  .map((value) => FormBuilderFieldOption(value: value))
                  .toList(),
              decoration: InputDecoration(labelText: 'Blood Group'),
            ),
            ],),),
            SizedBox(height: 100,),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                MaterialButton(
                  color: Theme.of(context).accentColor,
                  child: Text('Submit',
                    style: TextStyle(color: Colors.white),
                  ),
                  onPressed: () async {
                    //print(_formKey.currentState.mounted);
                    Map<String, dynamic> _donorMap;
                    if (_formKey.currentState.validate()) {
                      _formKey.currentState.save();
                      //print(_formKey.currentState.value);
                      _donorMap = {
                        ..._formKey.currentState.value,
                        'createdDate': DateTime.now()
                      };
                      print(_donorMap);
                      /*await BloodDonorsController()
                            .saveBloodDonors(widget.mode!, _donorMap);*/
                      ScaffoldMessenger.of(context).showSnackBar(
                        SnackBar(
                          content: Text('Add Donor Successful'),
                        ),
                      );
                      _formKey.currentState.reset();
                      //FocusScope.of(context).requestFocus(focusNode);
                    } else {
                      ScaffoldMessenger.of(context).showSnackBar(
                        SnackBar(
                          content: Text('Validation Failed'),
                        ),
                      );
                    }
                  },
                ),
                SizedBox(width: 20),
                MaterialButton(
                  color: Theme.of(context).accentColor,
                  child: Text(
                    "Reset",
                    style: TextStyle(color: Colors.white),
                  ),
                  onPressed: () {
                    _formKey.currentState.reset();
                  },
                ),
              ],
            )
          ],
        ),
      );
}