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

Exception has occurred when call ImageProvider.evict at state.dispose #77576

Closed
zmtzawqlp opened this issue Mar 8, 2021 · 23 comments · Fixed by #94902
Closed

Exception has occurred when call ImageProvider.evict at state.dispose #77576

zmtzawqlp opened this issue Mar 8, 2021 · 23 comments · Fixed by #94902
Assignees
Labels
a: images Loading, displaying, rendering images c: crash Stack traces logged to the console f: scrolling Viewports, list views, slivers, etc. found in release: 2.0 Found to occur in 2.0 framework flutter/packages/flutter repository. See also f: labels. has reproducible steps The issue has been confirmed reproducible and is ready to work on P1 High-priority issues at the top of the work list r: fixed Issue is closed as already fixed in a newer version

Comments

@zmtzawqlp
Copy link
Contributor

zmtzawqlp commented Mar 8, 2021

I want to remove image data from memory when image item is dispose.

Steps to Reproduce

1.run demo, scroll list

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, this.title}) : super(key: key);
  final String? title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<String> images = <String>[
    'https://photo.tuchong.com/4870004/f/298584322.jpg',
    'https://photo.tuchong.com/16389644/f/1303840119.jpg',
    'https://photo.tuchong.com/1924454/f/153280211.jpg',
    'https://photo.tuchong.com/1824846/f/601739531.jpg',
    'https://photo.tuchong.com/2353448/f/147183522.jpg',
    'https://photo.tuchong.com/2732194/f/514055506.jpg',
    'https://photo.tuchong.com/19454111/f/940639122.jpg',
    'https://photo.tuchong.com/12772247/f/950208723.jpg',
    'https://photo.tuchong.com/16389644/f/1303840119.jpg',
    'https://photo.tuchong.com/1924454/f/153280211.jpg',
    'https://photo.tuchong.com/1824846/f/601739531.jpg',
    'https://photo.tuchong.com/2353448/f/147183522.jpg',
    'https://photo.tuchong.com/2732194/f/514055506.jpg',
    'https://photo.tuchong.com/19454111/f/940639122.jpg',
    'https://photo.tuchong.com/12772247/f/950208723.jpg',
    'https://photo.tuchong.com/16389644/f/1303840119.jpg',
    'https://photo.tuchong.com/1924454/f/153280211.jpg',
    'https://photo.tuchong.com/1824846/f/601739531.jpg',
    'https://photo.tuchong.com/2353448/f/147183522.jpg',
    'https://photo.tuchong.com/2732194/f/514055506.jpg',
    'https://photo.tuchong.com/19454111/f/940639122.jpg',
    'https://photo.tuchong.com/12772247/f/950208723.jpg',
    'https://photo.tuchong.com/1824846/f/601739531.jpg',
    'https://photo.tuchong.com/20789574/f/1191315286.jpg',
    'https://photo.tuchong.com/2353448/f/147183522.jpg',
    'https://photo.tuchong.com/15809857/f/158194644.jpg',
    'https://photo.tuchong.com/16389644/f/1303840119.jpg',
    'https://photo.tuchong.com/1924454/f/153280211.jpg',
    'https://photo.tuchong.com/3193193/f/1176439059.jpg',
    'https://photo.tuchong.com/2353448/f/147183522.jpg',
    'https://photo.tuchong.com/2732194/f/514055506.jpg',
    'https://photo.tuchong.com/15809857/f/158194644.jpg',
    'https://photo.tuchong.com/12772247/f/950208723.jpg',
    'https://photo.tuchong.com/2992739/f/226216625.jpg',
    'https://photo.tuchong.com/1824846/f/601739531.jpg',
    'https://photo.tuchong.com/20789574/f/1191315286.jpg',
    'https://photo.tuchong.com/1755665/f/206885901.jpg',
    'https://photo.tuchong.com/16389644/f/673974708.jpg',
    'https://photo.tuchong.com/2353448/f/973145661.jpg',
    'https://photo.tuchong.com/19454111/f/940639122.jpg',
    'https://photo.tuchong.com/15809857/f/920060890.jpg',
    'https://photo.tuchong.com/2742991/f/587652854.jpg',
    'https://photo.tuchong.com/239828/f/350019176.jpg',
    'https://photo.tuchong.com/19702103/f/679282943.jpg',
    'https://photo.tuchong.com/2461600/f/813958177.jpg',
    'https://photo.tuchong.com/475156/f/560914063.jpg',
    'https://photo.tuchong.com/19750051/f/1264584179.jpg',
  ];
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title!),
      ),
      body: ListView.builder(
        itemBuilder: (context, index) {
          return ImageItem(images[index]);
        },
        itemCount: images.length,
      ),
    );
  }
}

class ImageItem extends StatefulWidget {
  ImageItem(this.uri);
  final String uri;
  @override
  _ImageItemState createState() => _ImageItemState();
}

class _ImageItemState extends State<ImageItem> {
  late NetworkImage imageProvider;
  @override
  void initState() {
    super.initState();
    imageProvider = NetworkImage(widget.uri);
  }

  @override
  void dispose() {
    imageProvider.evict();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Image(
      image: imageProvider,
    );
  }
}

Exception has occurred.

Exception has occurred.
_AssertionError ('package:flutter/src/painting/image_stream.dart': Failed assertion: line 326 pos 12: '_completer == null': is not true.)

_AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:46)
_AssertionError._throwNew (dart:core-patch/errors_patch.dart:36)
ImageStream.setCompleter (/Users/zmtzawqlp/Documents/flutter/stable/packages/flutter/lib/src/painting/image_stream.dart:326)
ImageProvider.resolve.<anonymous closure> (/Users/zmtzawqlp/Documents/flutter/stable/packages/flutter/lib/src/painting/image_provider.dart:337)
<asynchronous gap> (Unknown Source:0)

This is not found in v1.22.6

[✓] Flutter (Channel stable, 2.0.0, on macOS 11.0.1 20B29 darwin-x64, locale
    zh-Hans-CN)
    • Flutter version 2.0.0 at /Users/zmtzawqlp/Documents/flutter/stable
    • Framework revision 60bd88df91 (5 days ago), 2021-03-03 09:13:17 -0800
    • Engine revision 40441def69
    • Dart version 2.12.0
    • Pub download mirror https://pub.flutter-io.cn
    • Flutter download mirror https://storage.flutter-io.cn

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
    • Android SDK at /Users/zmtzawqlp/Library/Android/sdk
    • Platform android-30, build-tools 30.0.2
    • ANDROID_HOME = /Users/zmtzawqlp/Library/Android/sdk
    • Java binary at: /Applications/Android
      Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build
      1.8.0_242-release-1644-b3-6915495)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 12.4, Build version 12D4e
    • CocoaPods version 1.10.0

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 4.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build
      1.8.0_242-release-1644-b3-6915495)

[✓] VS Code (version 1.54.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.20.0

[✓] Connected device (3 available)
    • iPhone 12 Pro Max (mobile) • 2204B20F-9E1B-4872-9A94-A9A734D2BC02 • ios
      • com.apple.CoreSimulator.SimRuntime.iOS-14-4 (simulator)
    • macOS (desktop)            • macos                                •
      darwin-x64     • macOS 11.0.1 20B29 darwin-x64
    • Chrome (web)               • chrome                               •
      web-javascript • Google Chrome 88.0.4324.192
@darshankawar darshankawar added the in triage Presently being triaged by the triage team label Mar 8, 2021
@darshankawar
Copy link
Member

@zmtzawqlp
Tried your code sample on latest stable (2.0.1) using Android 8.1.0 device but didn't see the issue. Tapped push and immediately back button 8 to 10 times.

77576.mp4
flutter doctor -v
[✓] Flutter (Channel stable, 2.0.1, on Mac OS X 10.15.4 19E2269 darwin-x64,
    locale en-GB)
    • Flutter version 2.0.1 at /Users/dhs/documents/Fluttersdk/flutter
    • Framework revision c5a4b4029c (4 days ago), 2021-03-04 09:47:48 -0800
    • Engine revision 40441def69
    • Dart version 2.12.0

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.0)
    • Android SDK at /Users/dhs/Library/Android/sdk
    • Platform android-30, build-tools 30.0.0
    • Java binary at: /Applications/Android
      Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build
      1.8.0_242-release-1644-b3-6915495)
    • All Android licenses accepted.

[!] Xcode - develop for iOS and macOS
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 12.3, Build version 12C33
    ! CocoaPods 1.9.3 out of date (1.10.0 is recommended).
        CocoaPods is used to retrieve the iOS and macOS platform side's plugin
        code that responds to your plugin usage on the Dart side.
        Without CocoaPods, plugins will not work on iOS or macOS.
        For more info, see https://flutter.dev/platform-plugins
      To upgrade see
      https://guides.cocoapods.org/using/getting-started.html#installation for
      instructions.

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 4.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build
      1.8.0_242-release-1644-b3-6915495)

[✓] VS Code (version 1.54.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.18.1

[✓] Connected device (3 available)
    • SM A260G (mobile) • 5200763ebcfa861f • android-arm    • Android 8.1.0 (API
      27)
    • macOS (desktop)   • macos            • darwin-x64     • Mac OS X 10.15.4
      19E2269 darwin-x64
    • Chrome (web)      • chrome           • web-javascript • Google Chrome
      88.0.4324.192

! Doctor found issues in 1 category.

@darshankawar darshankawar added the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Mar 8, 2021
@zmtzawqlp
Copy link
Contributor Author

image is ready loaded, please try to change a big image.

and i will check it on 2.0.1, maybe it's already fixed

@no-response no-response bot removed the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Mar 8, 2021
@zmtzawqlp
Copy link
Contributor Author

It is found in 2.0.1 at my side too. please make sure the image is not loaded completed.

@darshankawar
Copy link
Member

@zmtzawqlp
I am unable to replicate it still. Can you provide a video / gif of the issue ?

@darshankawar darshankawar added the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Mar 9, 2021
@zmtzawqlp
Copy link
Contributor Author

@zmtzawqlp
I am unable to replicate it still. Can you provide a video / gif of the issue ?

I have updated the demo, maybe it's more easy to reproduce this issue

@no-response no-response bot removed the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Mar 10, 2021
@AlexV525
Copy link
Member

AlexV525 commented Mar 10, 2021

Reproduce on 2.0.1. Scroll the image list then error will appear.

[ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: Bad state: Stream has been disposed.
An ImageStream is considered disposed once at least one listener has been added and subsequently all listeners have been removed and no handles are outstanding from the keepAlive method.
To resolve this error, maintain at least one listener on the stream, or create an ImageStreamCompleterHandle from the keepAlive method, or create a new stream for the image.
#0      ImageStreamCompleter._checkDisposed (package:flutter/src/painting/image_stream.dart:572:7)
#1      ImageStreamCompleter.reportImageChunkEvent (package:flutter/src/painting/image_stream.dart:705:5)
#2      _rootRunUnary (dart:async/zone.dart:1362:47)
#3      _CustomZone.runUnary (dart:async/zone.dart:1265:19)
#4      _CustomZone.runUnaryGuarded (dart:async/zone.dart:1170:7)
#5      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#6      _DelayedData.perform (dart:async/stream_impl.dart:591:14)
#7      _StreamImplEvents.handleNext (dart:async/stream_impl.dart:706:11)
#8      _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:663:7)
#9      _rootRun (dart:async/zone.dart:1346:47)
#10     _CustomZone.run (dart:async/zone.dart:1258:19)
#11     _CustomZone.runGuarded (dart:async/zone.dart:1162:7)
#12     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1202:23)
#13     _rootRun (dart:async/zone.dart:1354:13)
#14     _CustomZone.run (dart:async/zone.dart:1258:19)
#15     _CustomZone.runGuarded (dart:async/zone.dart:1162:7)
#16     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1202:23)
#17     _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
#18     _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)
Example code
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, this.title}) : super(key: key);
  final String? title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<String> images = <String>[
    'https://photo.tuchong.com/4870004/f/298584322.jpg',
    'https://photo.tuchong.com/16389644/f/1303840119.jpg',
    'https://photo.tuchong.com/1924454/f/153280211.jpg',
    'https://photo.tuchong.com/1824846/f/601739531.jpg',
    'https://photo.tuchong.com/2353448/f/147183522.jpg',
    'https://photo.tuchong.com/2732194/f/514055506.jpg',
    'https://photo.tuchong.com/19454111/f/940639122.jpg',
    'https://photo.tuchong.com/12772247/f/950208723.jpg',
    'https://photo.tuchong.com/16389644/f/1303840119.jpg',
    'https://photo.tuchong.com/1924454/f/153280211.jpg',
    'https://photo.tuchong.com/1824846/f/601739531.jpg',
    'https://photo.tuchong.com/2353448/f/147183522.jpg',
    'https://photo.tuchong.com/2732194/f/514055506.jpg',
    'https://photo.tuchong.com/19454111/f/940639122.jpg',
    'https://photo.tuchong.com/12772247/f/950208723.jpg',
    'https://photo.tuchong.com/16389644/f/1303840119.jpg',
    'https://photo.tuchong.com/1924454/f/153280211.jpg',
    'https://photo.tuchong.com/1824846/f/601739531.jpg',
    'https://photo.tuchong.com/2353448/f/147183522.jpg',
    'https://photo.tuchong.com/2732194/f/514055506.jpg',
    'https://photo.tuchong.com/19454111/f/940639122.jpg',
    'https://photo.tuchong.com/12772247/f/950208723.jpg',
    'https://photo.tuchong.com/1824846/f/601739531.jpg',
    'https://photo.tuchong.com/20789574/f/1191315286.jpg',
    'https://photo.tuchong.com/2353448/f/147183522.jpg',
    'https://photo.tuchong.com/15809857/f/158194644.jpg',
    'https://photo.tuchong.com/16389644/f/1303840119.jpg',
    'https://photo.tuchong.com/1924454/f/153280211.jpg',
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title!),
      ),
      body: ListView.builder(
        itemBuilder: (context, index) {
          return ImageItem(images[index]);
        },
        itemCount: images.length,
      ),
    );
  }
}

class ImageItem extends StatefulWidget {
  ImageItem(this.uri);

  final String uri;

  @override
  _ImageItemState createState() => _ImageItemState();
}

class _ImageItemState extends State<ImageItem> {
  late final NetworkImage imageProvider = NetworkImage(widget.uri);

  @override
  void dispose() {
    imageProvider.evict();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Image(image: imageProvider);
  }
}
[✓] Flutter (Channel beta, 2.0.1, on macOS 11.1 20C69 darwin-x64, locale zh-Hans-CN)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[✓] Xcode - develop for iOS and macOS
[✓] Chrome - develop for the web
[✓] Android Studio (version 4.1)
[✓] IntelliJ IDEA Ultimate Edition (version 2020.3.1)
[✓] VS Code (version 1.53.2)
[✓] Connected device (2 available)

@darshankawar
Copy link
Member

@zmtzawqlp
With updated sample, I get below exception:

[VERBOSE-2:ui_dart_state.cc(186)] Unhandled Exception: Bad state: Stream has been disposed. An ImageStream is considered disposed once at least one listener has been added and subsequently all listeners have been removed and no handles are outstanding from the keepAlive method. To resolve this error, maintain at least one listener on the stream, or create an ImageStreamCompleterHandle from the keepAlive method, or create a new stream for the image. which seems to be related to Stream being disposed and a solution on how to avoid it.

Your original exception seems to be different and related to failure in assertion, _AssertionError ('package:flutter/src/painting/image_stream.dart': Failed assertion: line 326 pos 12: '_completer == null': is not true.)

@darshankawar darshankawar added the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Mar 10, 2021
@zmtzawqlp
Copy link
Contributor Author

Stream has been disposed. An ImageStream is considered disposed once at least one listener has been added and subsequently all listeners have been removed and no handles are outstanding from the keepAlive method

It's the same error as what Alex said. I want to know how to clear the image memory safety,thanks

@no-response no-response bot removed the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Mar 15, 2021
@darshankawar
Copy link
Member

@zmtzawqlp
Per the exception, did you try the solution mentioned in it ?

To resolve this error, maintain at least one listener on the stream, or create an ImageStreamCompleterHandle from the keepAlive method, or create a new stream for the image

@darshankawar darshankawar added the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Mar 15, 2021
@zmtzawqlp
Copy link
Contributor Author

This is no refer to the demo case, i just want to call ImageProvider. evict when List item is disposed and removed from Widget tree. Is there any solution that we can deallocate image memory when this image is removed from Widget tree.

@no-response no-response bot removed the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Mar 15, 2021
@darshankawar
Copy link
Member

This is no refer to the demo case, i just want to call ImageProvider. evict when List item is disposed and removed from Widget tree. Is there any solution that we can deallocate image memory when this image is removed from Widget tree.

@zmtzawqlp
If you want to knoow how to deallocate image memory, I'd suggest you to ask this question on support channels like StackOverflow, since it seems you need to know how to do it, rather than a bug in the framework.
If you agree, you may close this issue. If you disagree and think you are reporting this as a bug, confirm the same.

@darshankawar darshankawar added the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Mar 16, 2021
@zmtzawqlp
Copy link
Contributor Author

This api is worked in 1.22.6, but it's breaking in 2.0.0 . so i need to know why and how to use it.

@no-response no-response bot removed the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Mar 16, 2021
@darshankawar
Copy link
Member

flutter doctor -v

[✓] Flutter (Channel stable, 2.0.2, on Mac OS X 10.15.4 19E2269 darwin-x64,
    locale en-GB)
    • Flutter version 2.0.2 at /Users/dhs/documents/Fluttersdk/flutter
    • Framework revision 8962f6dc68 (4 days ago), 2021-03-11 13:22:20 -0800
    • Engine revision 5d8bf811b3
    • Dart version 2.12.1

[!] Xcode - develop for iOS and macOS
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 12.3, Build version 12C33
    ! CocoaPods 1.9.3 out of date (1.10.0 is recommended).
        CocoaPods is used to retrieve the iOS and macOS platform side's plugin
        code that responds to your plugin usage on the Dart side.
        Without CocoaPods, plugins will not work on iOS or macOS.
        For more info, see https://flutter.dev/platform-plugins
      To upgrade see
      https://guides.cocoapods.org/using/getting-started.html#installation for
      instructions.

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] VS Code (version 1.54.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.18.1

[✓] Connected device (3 available)
    • iPhone 12 Pro Max (mobile) • A5473606-0213-4FD8-BA16-553433949729 • ios
      • com.apple.CoreSimulator.SimRuntime.iOS-14-3 (simulator)
    • macOS (desktop)            • macos                                •
      darwin-x64     • Mac OS X 10.15.4 19E2269 darwin-x64
    • Chrome (web)               • chrome                               •
      web-javascript • Google Chrome 89.0.4389.82

! Doctor found issues in 1 category.

@darshankawar darshankawar added a: images Loading, displaying, rendering images f: scrolling Viewports, list views, slivers, etc. found in release: 2.0 Found to occur in 2.0 framework flutter/packages/flutter repository. See also f: labels. has reproducible steps The issue has been confirmed reproducible and is ready to work on c: crash Stack traces logged to the console labels Mar 16, 2021
@darshankawar darshankawar removed the in triage Presently being triaged by the triage team label Mar 16, 2021
@goderbauer
Copy link
Member

/cc @dnfield

@zmtzawqlp
Copy link
Contributor Author

zmtzawqlp commented Mar 20, 2021

it seems that we can evict image only if it has completed.

  /// An image that has been submitted to [ImageCache.putIfAbsent], but
  /// not yet completed.
  final bool pending;

  /// An image that has been submitted to [ImageCache.putIfAbsent], has
  /// completed, fits based on the sizing rules of the cache, and has not been
  /// evicted.
  ///
  /// Such images will be kept alive even if [live] is false, as long
  /// as they have not been evicted from the cache based on its sizing rules.
  final bool keepAlive;

  /// An image that has been submitted to [ImageCache.putIfAbsent] and has at
  /// least one listener on its [ImageStreamCompleter].
  ///
  /// Such images may also be [keepAlive] if they fit in the cache based on its
  /// sizing rules. They may also be [pending] if they have not yet resolved.
  final bool live;

we have no api to do such thing now, what i can see is do as following:

     imageProvider
        .obtainCacheStatus(configuration: ImageConfiguration.empty)
         .then((ImageCacheStatus? value) {
       if (value?.keepAlive ?? false) {
         widget.image.evict();
      }
    });

But how and when can i release these image which are not completed at that moment?

@zmtzawqlp
Copy link
Contributor Author

I'm a little confused about [ImageCache.evict], as what annotation said, it seems that if i evict with includeLive=false, it will not throw exception, but it failed. Maybe i have misconstrued for it. It's very kind if someone could clarify it.

bool evict(Object key, { bool includeLive = true }) {
  assert(includeLive != null);
  if (includeLive) {
    // Remove from live images - the cache will not be able to mark
    // it as complete, and it might be getting evicted because it
    // will never complete, e.g. it was loaded in a FakeAsync zone.
    // In such a case, we need to make sure subsequent calls to
    // putIfAbsent don't return this image that may never complete.
    final _LiveImage? image = _liveImages.remove(key);
    image?.dispose();
  }
  final _PendingImage? pendingImage = _pendingImages.remove(key);
  if (pendingImage != null) {
    if (!kReleaseMode) {
      Timeline.instantSync('ImageCache.evict', arguments: <String, dynamic>{
        'type': 'pending'
      });
    }
    pendingImage.removeListener();
    return true;
  }
  final _CachedImage? image = _cache.remove(key);
  if (image != null) {
    if (!kReleaseMode) {
      Timeline.instantSync('ImageCache.evict', arguments: <String, dynamic>{
        'type': 'keepAlive',
        'sizeInBytes': image.sizeBytes,
      });
    }
    _currentSizeBytes -= image.sizeBytes!;
    image.dispose();
    return true;
  }
  if (!kReleaseMode) {
    Timeline.instantSync('ImageCache.evict', arguments: <String, dynamic>{
      'type': 'miss',
    });
  }
  return false;
}

@mat100payette
Copy link

What's up with this ? Tagged Severe: Crash and no update since march ?
How are you supposed to evict an image from cache on dispose ?

@dnfield
Copy link
Contributor

dnfield commented Dec 8, 2021

Hm. I was tagged in this while I was away on some paternity leave and missed it when I got back. I can take a look now, I suspect there's a pretty simple fix.

@mat100payette
Copy link

Fwiw, here's what I have, and it sometimes throws the Bad state: Stream has been disposed. exception.

@override
Future<void> dispose() async {
  Future<void>.delayed(Duration.zero, () async {
    await NetworkImage(widget.src).evict();
  });
  super.dispose();
}

@dnfield dnfield self-assigned this Dec 9, 2021
@dnfield dnfield added the P1 High-priority issues at the top of the work list label Dec 9, 2021
@dnfield
Copy link
Contributor

dnfield commented Dec 9, 2021

I also think this isn't a "hard" crasher - we shouldn't let this happen, but it's not going to actually crash your application or prevent you from continuing to run.

@mat100payette
Copy link

I agree. What will be the preferred way to evict the images at dispose time once your fix lands though? Just making sure everything is clear here.

@dnfield
Copy link
Contributor

dnfield commented Dec 9, 2021

The code in this issue is fine. There's just a bug where MultiFrame isn't unhooking itself from chunk events, which network images report during download.

@darshankawar darshankawar added the r: fixed Issue is closed as already fixed in a newer version label Dec 13, 2021
@github-actions
Copy link

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Dec 27, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
a: images Loading, displaying, rendering images c: crash Stack traces logged to the console f: scrolling Viewports, list views, slivers, etc. found in release: 2.0 Found to occur in 2.0 framework flutter/packages/flutter repository. See also f: labels. has reproducible steps The issue has been confirmed reproducible and is ready to work on P1 High-priority issues at the top of the work list r: fixed Issue is closed as already fixed in a newer version
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants