searchfield icon indicating copy to clipboard operation
searchfield copied to clipboard

FocusNode listener is not removed

Open nvi9 opened this issue 6 months ago • 2 comments

Describe the bug When using SearchField with an external FocusNode provided, there is an exception coming from the listener attached to it. I think this is because the previously attached listener is still there after a dispose as it is not removed (with removeListener).

To Reproduce Steps to reproduce the behavior:

  1. Provide a FocusNode to the SearchField
  2. Make the widget tree rebuild
  3. Interact with the field (click / type)
  4. See error
  • [x] By clicking this checkbox, I confirm I am using the latest version of the package found on pub.dev/searchfield

Expected behavior

There should be no exception.

Actual behavior

════════ Exception caught by foundation library ════════════════════════════════
The following assertion was thrown while dispatching notifications for FocusNode:
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.

When the exception was thrown, this was the stack:
#0      State.context.<anonymous closure> (package:flutter/src/widgets/framework.dart:954:9)
framework.dart:954
#1      State.context (package:flutter/src/widgets/framework.dart:960:6)
framework.dart:960
#2      _SearchFieldState.initialize.<anonymous closure> (package:searchfield/src/searchfield.dart:467:13)
searchfield.dart:467
#3      ChangeNotifier.notifyListeners (package:flutter/src/foundation/change_notifier.dart:439:24)
change_notifier.dart:439
#4      FocusNode._notify (package:flutter/src/widgets/focus_manager.dart:1130:5)
focus_manager.dart:1130
#5      FocusManager.applyFocusChangesIfNeeded (package:flutter/src/widgets/focus_manager.dart:1987:12)
focus_manager.dart:1987
(elided 10 frames from dart:async)

Additional context

The issue is not present when there is no externally provided FocusNode, since it is disposed here:

https://github.com/maheshj01/searchfield/blob/29e794d60ee38b3b3daadd7cb4d0428d4f424696/lib/src/searchfield.dart#L428-L430

Based on my tests moving the listener function to a private method and eg. adding the else branch after these lines containing _searchFocus!.removeListener(_searchFocusListener); can solve this issue.

nvi9 avatar Apr 16 '25 14:04 nvi9