mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
_An alternative to https://github.com/flutter/flutter/pull/166130 using `addEphemeralErrorListener`. The following text is adapted from https://github.com/flutter/flutter/pull/166130._ **Problem:** Currently, when using an `Image` widget with an `errorBuilder`, if the widget is removed from the widget tree (e.g., due to navigation or `setState`) *after* the image loading process has started but *before* an asynchronous loading error is reported back, the error can still be reported via `FlutterError.reportError`. This occurs because the `_ImageState` listener is removed upon disposal, and the `ImageStreamCompleter` subsequently treats the error as unhandled, logging it despite the developer's intent to handle it via the `errorBuilder`. This leads to unexpected noise in logs and crash reporting systems. **Solution:** This PR utilizes `addEphemeralErrorListener`, which allows the image stream to be disposed while having an error reporter. The error will not be reported as long as there is an error reporter. The `Image` widget adds an empty error reporter if `errorBuilder` is not null. **Related Issues:** * Fixes #97077 * Related: #107416, #69125, #34451, Baseflow/flutter_cached_network_image#780 **Tests:** * Added a new test case `errorBuilder prevents FlutterError report even if widget is disposed` to `test/widgets/image_test.dart` to specifically verify the fix for the disposal race condition. * This test was written by @/perlycke in https://github.com/flutter/flutter/pull/166130. * Existing tests in `test/widgets/image_test.dart` (including golden tests like 'Failed image loads in debug mode') pass with these changes without requiring updates. **Breaking Changes:** * None. This change fixes incorrect behavior and preserves expected debug visuals. The internal mechanism for reporting errors when no `errorBuilder` is present has shifted, but the user-facing outcome is consistent. ## Pre-launch Checklist - [ ] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [ ] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [ ] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [ ] I signed the [CLA]. - [ ] I listed at least one issue that this PR fixes in the description above. - [ ] I updated/added relevant documentation (doc comments with `///`). - [ ] I added new tests to check the change I am making, or this PR is [test-exempt]. - [ ] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [ ] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md