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
587 stars 45 forks source link

fix animation controller disposed multiple times #102

Closed rebaz94 closed 3 months ago

payam-zahedi commented 6 months ago

Hey @rebaz94 Thanks for your contribution, can you tell us, where did you exactly add your changes? in the animated file?

Also can you send a link to the issue of the widget in flutter repo?

rebaz94 commented 6 months ago

Hi @payam-zahedi The fix inside _SliverAnimatedMultiBoxAdaptor class, I only dispose the controller if does not already disposed

@override
  void dispose() {
    for (final _ActiveItem item in _incomingItems.followedBy(_outgoingItems)) {
      if (!item.disposed && item.controller != null) {
        item.disposed = true;
        item.controller!.dispose();
      }
    }
    super.dispose();
  }

and also when removing item it make ensure dispose correctly:

void removeItem(int index, AnimatedRemovedItemBuilder builder, {Duration duration = _kDuration}) {
    assert(index >= 0);

    final int itemIndex = _indexToItemIndex(index);
    assert(itemIndex >= 0 && itemIndex < _itemsCount);
    assert(_activeItemAt(_outgoingItems, itemIndex) == null);

    final _ActiveItem? incomingItem = _removeActiveItemAt(_incomingItems, itemIndex);
    final AnimationController controller =
        incomingItem?.controller ?? AnimationController(duration: duration, value: 1.0, vsync: this);
    final _ActiveItem outgoingItem = _ActiveItem.outgoing(controller, itemIndex, builder);

    // --- added
    if (!mounted) return;

    setState(() {
      _outgoingItems
        ..add(outgoingItem)
        ..sort();
    });

    controller.reverse().then<void>((void value) {
      // --- added
      if (!mounted) return;

      final removedItem = _removeActiveItemAt(_outgoingItems, outgoingItem.itemIndex);
      // --- added
      if (removedItem != null) {
        if (!removedItem.disposed && removedItem.controller != null) {
          removedItem.controller!.dispose();
          removedItem.disposed = true;
        }
      }

      // Decrement the incoming and outgoing item indices to account
      // for the removal.
      for (final _ActiveItem item in _incomingItems) {
        if (item.itemIndex > outgoingItem.itemIndex) {
          item.itemIndex -= 1;
        }
      }
      for (final _ActiveItem item in _outgoingItems) {
        if (item.itemIndex > outgoingItem.itemIndex) {
          item.itemIndex -= 1;
        }
      }

      setState(() => _itemsCount -= 1);
    });
  }

Also can you send a link to the issue of the widget in flutter repo?

Sorry I'm not sure if there is any issue exist for that.

movaid7 commented 6 months ago

Can this be merged? @payam-zahedi

payam-zahedi commented 5 months ago

@movaid7 I need to investigate about the side effects

payam-zahedi commented 3 months ago

Hey @rebaz94 Thanks for your contribution but I think we need to fix this on Flutter soruce code

So I will close this PR and will try to fix it there

movaid7 commented 3 months ago

Hey @rebaz94 Thanks for your contribution but I think we need to fix this on Flutter soruce code

So I will close this PR and will try to fix it there

Please link to the Flutter issue once created