Skip to content

fix: dispose queued animation frame when image completer is disposed - #1065

Open
kevmo314 wants to merge 7 commits into
Baseflow:mainfrom
kevmo314:fix/dispose-queued-animation-frame
Open

kevmo314 wants to merge 7 commits into
Baseflow:mainfrom
kevmo314:fix/dispose-queued-animation-frame

Conversation

@kevmo314

@kevmo314 kevmo314 commented Oct 26, 2026 •

Copy link
Copy Markdown

✨ What kind of change does this PR introduce? (Bug fix, feature, docs update...)

Bug fix: release queued animation frames, codecs, and subscriptions when the image stream completer is disposed.

⤵️ What is the current behavior?

Removing animated images can leave a decoded frame, the active codec, and a pending refresh codec undisposed. The codec subscription also remains active. Synchronous final-listener removal during delivery can invalidate the frame before its duration is read.

🆕 What is the new behavior (if this is a feature change)?

Cleanup uses the framework's onDisposed() hook, replacing the duplicate keep-alive counters and handle wrapper. Final disposal releases queued frames and active/pending codecs and cancels chunk events. Static callbacks drain and dispose late codec results without retaining the completer; cancelling during codec creation would drop those results undisposed. Replaced codecs are disposed, including superseded pending refreshes; stale decode results are released and stale decode errors ignored.

Frame delivery transfers ownership before notifying listeners and stops decoding when the last listener removes itself, while preserving keep-alive and resume behavior. At cycle boundaries, a pending refresh is selected before pausing so it is available on resume. Codec activation drops superseded pending refreshes, including after pause/resume; synchronous codec replacement during delivery preserves the new animation's frame count. Constructor documentation makes codec ownership explicit. Shared helpers centralize queued-frame cleanup and regression-test setup. Version and changelog are updated to 4.0.6.

💥 Does this PR introduce a breaking change?

No.

🐛 Recommendations for testing

  • flutter test --coverage: all 71 package tests pass.
  • flutter analyze and formatting checks for changed Dart files pass.
  • Regression coverage includes queued-frame disposal, synchronous listener removal, active/pending codec disposal and replacement, late codec delivery from futures and async generators, in-flight decode completion/errors, disposal before listener registration, keep-alive pause/resume, three-codec refresh ordering, and synchronous refresh during delivery.
  • Independent agy review verified the pending-refresh cleanup, synchronous replacement handling, and ownership documentation. Three additional animation timing/resume findings also reproduce on unchanged main and are outside this disposal fix.
  • Example builds were not run locally; check CI.

📝 Links to relevant issues/docs

Related: #1064 addresses codec subscription cancellation. This PR also releases decoded frames and codecs through the framework disposal lifecycle.

🤔 Checklist before submitting

  • All projects build
  • Follows style guide lines (code style guide)
  • Relevant documentation was updated
  • Rebased onto current main

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Synchronous removal of the final listener during frame delivery can trigger double disposal or invalidate the frame reference before its duration is read.

1 open issue
What changed in this PR

This PR fixes a decoded animation-frame leak in MultiImageStreamCompleter, complementing #1064’s codec subscription cleanup.

Changes:

  • Dispose and clear queued frames during final disposal while preserving keep-alive behavior.
  • Add three regression tests covering queued frames and final keep-alive release.
  • Bump the app-facing package to 4.0.6 and document the fix.
File Description
cached_network_image/​test/​image_stream_completer_test.dart Add queued-frame disposal and keep-alive regression tests.
cached_network_image/​pubspec.yaml Bump version to 4.0.6.
cached_network_image/​lib/​src/​image_provider/​multi_image_stream_completer.dart Release the queued frame during final disposal.
cached_network_image/​CHANGELOG.md Document the animation-frame leak fix.

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings October 26, 2026 03:34

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The focused ownership fix has targeted regression coverage for the affected disposal paths, with no unresolved issues identified.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

Comment thread cached_network_image/lib/src/image_provider/multi_image_stream_completer.dart Outdated
Comment thread cached_network_image/lib/src/image_provider/multi_image_stream_completer.dart Outdated
Comment thread cached_network_image/lib/src/image_provider/multi_image_stream_completer.dart Outdated
Comment thread cached_network_image/lib/src/image_provider/multi_image_stream_completer.dart Outdated
Comment thread cached_network_image/test/image_stream_completer_test.dart
Copilot AI balanced review requested due to automatic review settings October 28, 2026 04:57

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Listener removal can leave a refresh codec pending indefinitely, while cancelling a subscription during codec creation can leak an undelivered codec.

2 open issues

Review effort: Balanced

Comment thread cached_network_image/lib/src/image_provider/multi_image_stream_completer.dart Outdated
Comment thread cached_network_image/lib/src/image_provider/multi_image_stream_completer.dart Outdated
Copilot AI balanced review requested due to automatic review settings October 28, 2026 05:19

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues were identified in the resource-cleanup and animation-lifecycle changes.

No open issues 🎉

2 resolved since last review

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings October 28, 2026 08:47

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues were identified in the resource-cleanup changes to MultiImageStreamCompleter.

No open issues 🎉

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings October 28, 2026 08:55

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues remain for the resource-cleanup and animation-lifecycle changes.

No open issues 🎉

Review effort: Balanced

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.

3 participants