payam-zahedi / toastification

Toastification is a Flutter package for displaying customizable toast messages. It provides predefined widgets for success, error, warning, and info messages, as well as a custom widget for flexibility. With Toastification, you can add and manage multiple toast messages at the same time with ease.
https://payamzahedi.com/toastification/
BSD 3-Clause "New" or "Revised" License
470 stars 31 forks source link

Exception on close toastification manually [Probably only in flutter web] #54

Open codingwithsaeed opened 8 months ago

codingwithsaeed commented 8 months ago

Describe the bug This error occurs when I hit the close button.

Screenshots exception

Flutter information:

callmephil commented 8 months ago

I have the same issue on the web, it looks like it only happens when the progress bar option is set to true.

https://github.com/payam-zahedi/toastification/assets/2213079/75f5a572-3818-47a8-9c79-b8b0bec93034

payam-zahedi commented 8 months ago

I couldn't find a solution for this.

Basically, I don't know how it is happening.

My guess is that it is related to Animated List and it's a bug of the flutter.

payam-zahedi commented 8 months ago

I have the same issue on the web, it looks like it only happens when the progress bar option is set to true. Screen.Recording.2023-10-31.at.10.07.10.PM.mov

I could reproduce it even without progress bar

p4-k4 commented 4 months ago

This is still an issue on flutter web.

Flutter 3.19.2 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 7482962148 (5 days ago) • 2024-02-27 16:51:22 -0500
Engine • revision 04817c99c9
Tools • Dart 3.3.0 • DevTools 2.31.1
Trung15010802 commented 3 months ago

any update ?

andynvt commented 3 months ago

any update ? Right after the toast is dismissed from screen, the error will show

Flutter 3.16.9 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 41456452f2 (7 weeks ago) • 2024-01-25 10:06:23 -0800
Engine • revision f40e976bed
Tools • Dart 3.2.6 • DevTools 2.28.5
Trung15010802 commented 3 months ago

Wrap it with Future.delay: image

andynvt commented 3 months ago

Wrap it with Future.delay: image

Does this work @Trung15010802 ?

Trung15010802 commented 3 months ago

Wrap it with Future.delay: image

Does this work @Trung15010802 ?

It's work for me. I don't see any error

payam-zahedi commented 3 months ago

The problem is we don't have enough information to fix this

I'm not really sure what is the exact problem

andynvt commented 3 months ago

Wrap it with Future.delay: image

Does this work @Trung15010802 ?

It's work for me. I don't see any error

Thanks @Trung15010802. I've realized that addPostFrameCallback also works.

WidgetsBinding.instance.addPostFrameCallback(() => toastification.show());
ErsinMandaci commented 3 months ago

Turning off this code in the ToastificationManager class fixes the error but you lose the return animation.

// if (showRemoveAnimation) { // _listGlobalKey.currentState?.removeItem( // index, // (BuildContext context, Animation animation) { // return ToastHolderWidget( // item: removedItem, // animation: animation, // alignment: alignment, // transformerBuilder: _toastAnimationBuilder(removedItem), // ); // }, // duration: _createAnimationDuration(removedItem), // );

  //    if the [showRemoveAnimation] is false, we will remove the notification
  //   without showing the remove animation.
  // } else {
  //   _listGlobalKey.currentState?.removeItem(
  //     index,
  //     (BuildContext context, Animation<double> animation) {
  //       return const SizedBox.shrink();
  //     },
  //   );
  // } 
payam-zahedi commented 3 months ago

Turning off this code in the ToastificationManager class fixes the error but you lose the return animation.

// if (showRemoveAnimation) { // _listGlobalKey.currentState?.removeItem( // index, // (BuildContext context, Animation animation) { // return ToastHolderWidget( // item: removedItem, // animation: animation, // alignment: alignment, // transformerBuilder: _toastAnimationBuilder(removedItem), // ); // }, // duration: _createAnimationDuration(removedItem), // );

  //    if the [showRemoveAnimation] is false, we will remove the notification
  //   without showing the remove animation.
  // } else {
  //   _listGlobalKey.currentState?.removeItem(
  //     index,
  //     (BuildContext context, Animation<double> animation) {
  //       return const SizedBox.shrink();
  //     },
  //   );
  // } 

This is not the solution

This not make sense to disable the return animation

we should find the exact problem

ErsinMandaci commented 3 months ago

Turning off this code in the ToastificationManager class fixes the error but you lose the return animation. // if (showRemoveAnimation) { // _listGlobalKey.currentState?.removeItem( // index, // (BuildContext context, Animation animation) { // return ToastHolderWidget( // item: removedItem, // animation: animation, // alignment: alignment, // transformerBuilder: _toastAnimationBuilder(removedItem), // ); // }, // duration: _createAnimationDuration(removedItem), // );

  //    if the [showRemoveAnimation] is false, we will remove the notification
  //   without showing the remove animation.
  // } else {
  //   _listGlobalKey.currentState?.removeItem(
  //     index,
  //     (BuildContext context, Animation<double> animation) {
  //       return const SizedBox.shrink();
  //     },
  //   );
  // } 

This is not the solution

This not make sense to disable the return animation

we should find the exact problem

Yes, I agree, I offered a suggestion as a temporary solution. Now as an advanced stage //duration: _createAnimationDuration(removedItem), in the comment line eliminated the error. However, I could not understand exactly what _createAnimationDuration does as a function.

if (showRemoveAnimation) {
    _listGlobalKey.currentState?.removeItem(
      index,
      (BuildContext context, Animation<double> animation) {
        return ToastHolderWidget(
          item: removedItem,
          animation: animation,
          alignment: alignment,
          transformerBuilder: _toastAnimationBuilder(removedItem),
        );
      },
      //duration: _createAnimationDuration(removedItem),
    );
  }
KeithEyreDFM commented 2 months ago

I have the same issue on the web, it looks like it only happens when the progress bar option is set to true. Screen.Recording.2023-10-31.at.10.07.10.PM.mov

I could reproduce it even without progress bar

Same :(

KeithEyreDFM commented 2 months ago

Wrap it with Future.delay: image

Does this work @Trung15010802 ?

It's work for me. I don't see any error

Thanks @Trung15010802. I've realized that addPostFrameCallback also works.

WidgetsBinding.instance.addPostFrameCallback(() => toastification.show());

Didn't work. Not did wrapping it in a Future(Duration.zero) :(

WidgetsBinding.instance.addPostFrameCallback((_) => toastification.show(
            context: context,
            type: ToastificationType.error,
            style: ToastificationStyle.flatColored,
            icon: const Icon(Icons.error_outline_rounded),
            title: const Text('No Items Available'),
            alignment: Alignment.topRight,
            autoCloseDuration: const Duration(seconds: 4),
            borderRadius: BorderRadius.circular(12.0),
            applyBlurEffect: true,
          ));

This also did not work. The crash still happens:

Future.delayed(Duration.zero, () {
  toastification.show(
    context: context,
    type: ToastificationType.error,
    style: ToastificationStyle.flatColored,
    icon: const Icon(Icons.error_outline_rounded),
    title: const Text('No Items Available'),
    alignment: Alignment.topRight,
    autoCloseDuration: const Duration(seconds: 4),
    borderRadius: BorderRadius.circular(12.0),
    applyBlurEffect: true,
  );
});

Error:

Error: AnimationController.dispose() called more than once. A given AnimationController cannot be disposed more than once. The following AnimationController object was disposed multiple times: AnimationController#d8f82(⏮ 0.000; paused; DISPOSED) dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 297:3 throw_ packages/flutter/src/animation/animation_controller.dart 823:9 <fn> packages/flutter/src/animation/animation_controller.dart 833:14 dispose packages/flutter/src/widgets/animated_scroll_view.dart 1198:55 <fn> dart-sdk/lib/async/zone.dart 1661:54 runUnary dart-sdk/lib/async/future_impl.dart 162:18 handleValue dart-sdk/lib/async/future_impl.dart 838:44 handleValueCallback dart-sdk/lib/async/future_impl.dart 867:13 _propagateToListeners dart-sdk/lib/async/future_impl.dart 643:5 [_completeWithValue] dart-sdk/lib/async/future_impl.dart 713:7 callback dart-sdk/lib/async/schedule_microtask.dart 40:11 _microtaskLoop dart-sdk/lib/async/schedule_microtask.dart 49:5 _startMicrotaskLoop dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 181:7 <fn>

Trung15010802 commented 2 months ago

Wrap it with Future.delay: image

Does this work @Trung15010802 ?

It's work for me. I don't see any error

Thanks @Trung15010802. I've realized that addPostFrameCallback also works.

WidgetsBinding.instance.addPostFrameCallback(() => toastification.show());

Didn't work. Not did wrapping it in a Future(Duration.zero) :(

WidgetsBinding.instance.addPostFrameCallback((_) => toastification.show(
           context: context,
           type: ToastificationType.error,
           style: ToastificationStyle.flatColored,
           icon: const Icon(Icons.error_outline_rounded),
           title: const Text('No Items Available'),
           alignment: Alignment.topRight,
           autoCloseDuration: const Duration(seconds: 4),
           borderRadius: BorderRadius.circular(12.0),
           applyBlurEffect: true,
         ));

This also did not work. The crash still happens:

Future.delayed(Duration.zero, () {
  toastification.show(
    context: context,
    type: ToastificationType.error,
    style: ToastificationStyle.flatColored,
    icon: const Icon(Icons.error_outline_rounded),
    title: const Text('No Items Available'),
    alignment: Alignment.topRight,
    autoCloseDuration: const Duration(seconds: 4),
    borderRadius: BorderRadius.circular(12.0),
    applyBlurEffect: true,
  );
});

Error:

Error: AnimationController.dispose() called more than once. A given AnimationController cannot be disposed more than once. The following AnimationController object was disposed multiple times: AnimationController#d8f82(⏮ 0.000; paused; DISPOSED) dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 297:3 throw_ packages/flutter/src/animation/animation_controller.dart 823:9 <fn> packages/flutter/src/animation/animation_controller.dart 833:14 dispose packages/flutter/src/widgets/animated_scroll_view.dart 1198:55 <fn> dart-sdk/lib/async/zone.dart 1661:54 runUnary dart-sdk/lib/async/future_impl.dart 162:18 handleValue dart-sdk/lib/async/future_impl.dart 838:44 handleValueCallback dart-sdk/lib/async/future_impl.dart 867:13 _propagateToListeners dart-sdk/lib/async/future_impl.dart 643:5 [_completeWithValue] dart-sdk/lib/async/future_impl.dart 713:7 callback dart-sdk/lib/async/schedule_microtask.dart 40:11 _microtaskLoop dart-sdk/lib/async/schedule_microtask.dart 49:5 _startMicrotaskLoop dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 181:7 <fn>

Yes, it's still have error but not much like before. I have switched to another packge

rebaz94 commented 2 months ago

@payam-zahedi The issue is in the implementation of AnimatedList, where dispose is called multiple times in different places. I fixied and now works without any exceptions. Until the fix is officially implemented, we can utilize the modified AnimatedList. Here's the PR #102

komakur commented 1 month ago

@rebaz94 If the issue is really in AnimatedList, and you know what causes the problem, it would be nice if you create a reproducible code without toastification package, and open the issue on flutter repo

LeadcodeDev commented 1 month ago

Wrap it with Future.delay: image

It work for me, find my implementation below :

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:toastification/toastification.dart';

void createSuccessToast(BuildContext context,
        {required String label,
        String? description,
        Duration? duration = const Duration(seconds: 5)}) =>
    Future.delayed(
        Duration.zero,
        () => toastification.show(
            context: context,
            title: Text(label),
            style: ToastificationStyle.flat,
            autoCloseDuration: duration,
            alignment: Alignment.topRight,
            description: description != null
                ? RichText(text: TextSpan(text: description))
                : null,
            boxShadow: const [
              BoxShadow(
                color: Color(0x07000000),
                blurRadius: 16,
                offset: Offset(0, 16),
                spreadRadius: 0,
              )
            ],
            type: ToastificationType.success));
hongsw commented 3 days ago
    showProgressBar: false, // this is probably what is fixing the issue
payam-zahedi commented 2 days ago

@rebaz94 If the issue is really in AnimatedList, and you know what causes the problem, it would be nice if you create a reproducible code without toastification package, and open the issue on flutter repo

We already have one issue for this on flutter repo