Skip to content

Fix memory leaks in the editor, selection overlay, and toolbar - #5

Merged
ppamorim merged 3 commits into
masterfrom
feature/memoryLeak
Oct 7, 2026
Merged

ppamorim merged 3 commits into
masterfrom
feature/memoryLeak

Conversation

@ppamorim

@ppamorim ppamorim commented Oct 7, 2026

Copy link
Copy Markdown

Summary

Fixes the flutter_quill leaks reported by the app's UI-test leak tracker, plus several more found while auditing the library. Several of these kept the whole editor state reachable after unmount.

Objects never disposed

  • composingRange and _floatingCursorResetController in QuillRawEditorState
  • CursorCont._floatingCursorTextPosition
  • QuillEditorState.dragOffsetNotifier
  • RenderEditor._selectionStartInViewport / _selectionEndInViewport
  • Selection handle and toolbar OverlayEntrys (were only remove()d)
  • Web-only FocusNode and ClipboardStatusNotifier recreated on every build
  • ColorPickerDialog hex TextEditingController

Listeners that retained the editor

  • WidgetsBinding observer was only removed on blur, so disposing a focused editor leaked it
  • Listener on the external ScrollController never removed
  • Focus listener removal skipped when readOnly changed
  • Anonymous focus listener in QuillEditorState could never be removed
  • History buttons never cancelled their controller.changes subscription
  • iOS-simulator check could subscribe after dispose
  • didUpdateWidget removed _didChangeTextEditingValue but initState added _didChangeTextEditingValueListener, so swapping controllers left the editor attached to the old one

Breaking change

QuillEditor.focusNode and scrollController are now optional. When omitted, the editor creates and disposes its own (previously QuillEditor.basic allocated new ones on every build and never disposed them). Use QuillEditorState.focusNode for the effective node. flutter_quill_test helpers now read the node from QuillRawEditor's config, and the root pubspec overrides flutter_quill_test to the local path.

Test plan

  • flutter test (103 passing), including new test/editor/editor_leak_test.dart with leak tracking enabled. It reports 11 notDisposed objects against the old code and none with this change.
  • flutter test in flutter_quill_test
  • Re-run the app's full UI test against this branch and confirm the flutter_quill classes drop out of the notDisposed report

- Dispose notifiers, controllers and overlay entries the editor creates.
- Remove listeners/observers registered on external objects on dispose.
- Fix controller swap removing a different listener than was added.
- QuillEditor focusNode/scrollController are optional and owned by the state when omitted.
- Add leak-tracking widget tests.
Record the 11.5.0 changelog for the focus node, leak fixes, and native bridge fork.
Flutter stable rejects Gradle 8.7, so the wrapper, Android Gradle plugin, Kotlin, and Java target move to the current template versions.
@ppamorim
ppamorim merged commit dce7182 into master Oct 7, 2026
7 checks passed
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

Successfully merging this pull request may close these issues.

1 participant