Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get a "Unhandled Exception: This widget has been unmounted" when selecting an item #51

Closed
bondjpf opened this issue Sep 20, 2021 · 7 comments

Comments

@bondjpf
Copy link

bondjpf commented Sep 20, 2021

Full error:
[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: This widget has been unmounted, so the State no longer has a context (and should be considered defunct).
Consider canceling any active work during "dispose" or using the "mounted" getter to determine if the State is still active.
#0 State.context. (package:flutter/src/widgets/framework.dart:909:9)
#1 State.context (package:flutter/src/widgets/framework.dart:915:6)
#2 _SearchChoicesState.showDialogOrMenu (package:search_choices/search_choices.dart:1196:39)

#3 _SearchChoicesState.build. (package:search_choices/search_choices.dart:1277:21)

Here's the code:

Widget selectVehicle() {

  return Column(
      children: [
        Padding(
          padding: const EdgeInsets.only(left: 0.0, right: 0.0, top: 10.0),
          child: Row(
            children: <Widget>[
              WidgetAnimator(
                Text(
                  LocaleText.of(context).vehicle,
                  textAlign: TextAlign.left,
                  style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
                ),
              ),
            ],
            mainAxisAlignment: MainAxisAlignment.start,
          ),
        ),
        DecoratedBox(
          decoration: ShapeDecoration(
            color: Colors.transparent,
            shape: RoundedRectangleBorder(
              side: BorderSide(
                  width: 3.0,
                  style: BorderStyle.solid,
                  color: Theme.of(context).textTheme.caption.color),
              borderRadius: BorderRadius.all(Radius.circular(10.0)),
            ),
          ),
          child: Padding(
            padding: const EdgeInsets.only(top: 0.0, left: 0, right: 0),
            //child: SearchableDropdown(
            child: SearchChoices.single(
              hint: Text(
                '${selectedVehicle['name'] != null ? selectedVehicle['name'] : LocaleText.of(context).unassigned}',
                style: new TextStyle(
                  fontSize: 14,
                  color: Theme.of(context).textTheme.subtitle2.color,
                ),
                overflow: TextOverflow.ellipsis,
              ),
              underline: SizedBox(),
              key: UniqueKey(),
              items: devicesList?.map((item) {
                return new DropdownMenuItem<dynamic>(
                    child: ListWidgetAnimator(
                      Text(
                        '${item['name']} ${item['brand']} ${item['model']}',
                        style: new TextStyle(
                          fontSize: 14,
                          color: Theme.of(context).textTheme.subtitle2.color,
                        ),
                        overflow: TextOverflow.ellipsis,
                      ),
                    ),
                    value: item);
              })?.toList(),
              selectedValueWidgetFn: (item) {
                return Container(
                  transform: Matrix4.translationValues(0, 0, 0),
                  alignment: Alignment.centerLeft,
                  child: Text(
                    '${item['name']} ${item['brand']} ${item['model']}',
                    style: new TextStyle(
                      fontSize: 16,
                      color: Theme.of(context).textTheme.subtitle2.color,
                    ),
                    overflow: TextOverflow.ellipsis,
                  ),
                );
              },

              menuBackgroundColor: Theme.of(context).textTheme.headline4.color,
              isExpanded: true,
              value: selectedVehicle,
              isCaseSensitiveSearch: false,
              searchHint: new Text(
                LocaleText.of(context).selectEquipmentError,
                overflow: TextOverflow.ellipsis,
                style: new TextStyle(
                  fontSize: 14,
                ),
              ),
              searchFn: (String keyword, items) {
                List<int> ret = List<int>();
                if (keyword != null && items != null && keyword.isNotEmpty) {
                  keyword.split(" ").forEach((k) {
                    int i = 0;
                    items.forEach((item) {
                      if (k.isNotEmpty &&
                          (item.value['name']
                                  .toString()
                                  .toLowerCase()
                                  .contains(k.toLowerCase()) ||
                              item.value['brand']
                                  .toString()
                                  .toLowerCase()
                                  .contains(k.toLowerCase()) ||
                              item.value['model']
                                  .toString()
                                  .toLowerCase()
                                  .contains(k.toLowerCase()) ||
                              item.value['description']
                                  .toString()
                                  .toLowerCase()
                                  .contains(k.toLowerCase()))) {
                        ret.add(i);
                      }
                      i++;
                    });
                  });
                }
                if (keyword.isEmpty) {
                  ret = Iterable<int>.generate(items.length).toList();
                }
                return (ret);
              },

              closeButton: LocaleText.of(context).cancel,
              onChanged: (value) {
               
                // Hide keyboard
                FocusScope.of(context).unfocus();

                if (value != null) {
                  selectedVehicle = value;
                  if (mounted)
                    setState(() {
                     
                    });
                }
              },
            ),
          ),
        ),
      ],
    );
}```
@bondjpf bondjpf changed the title Get a "Unhandled Exception: This widget has been unmounted when selecting an item Get a "Unhandled Exception: This widget has been unmounted" when selecting an item Sep 20, 2021
@lcuis
Copy link
Owner

lcuis commented Sep 20, 2021

Hello @bondjpf ,

Thanks for raising this issue here.

Here is the Widget I derived from your example:

Column(
        children: [
          // Padding(
          // padding: const EdgeInsets.only(left: 0.0, right: 0.0, top: 10.0),
          // child: Row(
          // children: <Widget>[
          // WidgetAnimator(
          // Text(
          // LocaleText.of(context).vehicle,
          // textAlign: TextAlign.left,
          // style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
          // ),
          // ),
          // ],
          // mainAxisAlignment: MainAxisAlignment.start,
          // ),
          // ),
          DecoratedBox(
            decoration: ShapeDecoration(
              color: Colors.transparent,
              shape: RoundedRectangleBorder(
                side: BorderSide(
                  width: 3.0,
                  style: BorderStyle.solid,
                  // color: Theme.of(context).textTheme.caption.color
                ),
                borderRadius: BorderRadius.all(Radius.circular(10.0)),
              ),
            ),
            child: Padding(
              padding: const EdgeInsets.only(top: 0.0, left: 0, right: 0),
              //child: SearchableDropdown(
              child: SearchChoices.single(
                hint: Text(
                  // '${selectedVehicle['name'] != null ? selectedVehicle['name'] : LocaleText.of(context).unassigned}',
                  "some text",
                  style: new TextStyle(
                    fontSize: 14,
                    // color: Theme.of(context).textTheme.subtitle2.color,
                  ),
                  overflow: TextOverflow.ellipsis,
                ),
                underline: SizedBox(),
                key: UniqueKey(),
                items: items,
                // items: devicesList?.map((item) {
                // return new DropdownMenuItem<dynamic>(
                // child: ListWidgetAnimator(
                // Text(
                // '${item['name']} ${item['brand']} ${item['model']}',
                // style: new TextStyle(
                // fontSize: 14,
                // color: Theme.of(context).textTheme.subtitle2.color,
                // ),
                // overflow: TextOverflow.ellipsis,
                // ),
                // ),
                // value: item);
                // })?.toList(),
                selectedValueWidgetFn: (item) {
                  return Container(
                    transform: Matrix4.translationValues(0, 0, 0),
                    alignment: Alignment.centerLeft,
                    child: Text(
                      // '${item['name']} ${item['brand']} ${item['model']}',
                      item.toString(),
                      style: new TextStyle(
                        fontSize: 16,
                        // color: Theme.of(context).textTheme.subtitle2.color,
                      ),
                      overflow: TextOverflow.ellipsis,
                    ),
                  );
                },

                // menuBackgroundColor: Theme.of(context).textTheme.headline4.color,
                isExpanded: true,
                // value: selectedVehicle,
                value: selectedValueSingleDialog,
                isCaseSensitiveSearch: false,
                // searchHint: new Text(
                // LocaleText.of(context).selectEquipmentError,
                // overflow: TextOverflow.ellipsis,
                // style: new TextStyle(
                // fontSize: 14,
                // ),
                // ),
                searchFn: (String keyword, items) {
                  // List<int> ret = List<int>();
                  List<int> ret = [];
                  if (keyword != null && items != null && keyword.isNotEmpty) {
                    keyword.split(" ").forEach((k) {
                      int i = 0;
                      items.forEach((item) {
                        if (k.isNotEmpty &&
                            (item.value['name']
                                    .toString()
                                    .toLowerCase()
                                    .contains(k.toLowerCase()) ||
                                item.value['brand']
                                    .toString()
                                    .toLowerCase()
                                    .contains(k.toLowerCase()) ||
                                item.value['model']
                                    .toString()
                                    .toLowerCase()
                                    .contains(k.toLowerCase()) ||
                                item.value['description']
                                    .toString()
                                    .toLowerCase()
                                    .contains(k.toLowerCase()))) {
                          ret.add(i);
                        }
                        i++;
                      });
                    });
                  }
                  if (keyword.isEmpty) {
                    ret = Iterable<int>.generate(items.length).toList();
                  }
                  return (ret);
                },

                // closeButton: LocaleText.of(context).cancel,
                onChanged: (value) {
                  // Hide keyboard
                  FocusScope.of(context).unfocus();

                  if (value != null) {
                    // selectedVehicle = value;
                    selectedValueSingleDialog = value;
                    if (mounted) setState(() {});
                  }
                },
              ),
            ),
          ),
        ],
      )

I was not able to reproduce your error. Sorry about that.

The value is selected and displayed without any problem.

Is there anything else I can do to help?

@bondjpf
Copy link
Author

bondjpf commented Sep 21, 2021

Hi, thanks for taking the time to look into this.
What I did was just to replace SearchableDropdown with SearchChoices.single. Nothing more so I was expecting it would work right away.
I was experimenting a bit more and if I don't select any item and just close it, it will show the error.
Seems that there's a setState somewhere in the code that's triggering all this?

PS: If I try with 1.0.17, it works...

@lcuis
Copy link
Owner

lcuis commented Sep 21, 2021

Oh, I see. Thanks for your perseverance. I think I corrected. I am testing and will let you know when the latest version is deployed to pub.dev for you to use.

Sorry for the disruption. This was because I introduced the use of context with a more flexible onChanged.

@bondjpf
Copy link
Author

bondjpf commented Sep 21, 2021

Nice, looking forward to it, thanks

lcuis added a commit that referenced this issue Sep 21, 2021
Use of context for onChange was potentially breaking situations where Widget was already disposed. Thanks @bondjpf #51
@lcuis
Copy link
Owner

lcuis commented Sep 21, 2021

I hope latest search_choices plugin version 2.0.14 just published to pub.dev solves your issue.

@bondjpf
Copy link
Author

bondjpf commented Sep 21, 2021

It works. Thanks a lot.

@lcuis
Copy link
Owner

lcuis commented Sep 21, 2021

Great, thanks a lot to you @bondjpf for raising this and for the confirmation!

@lcuis lcuis closed this as completed Sep 21, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants