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

Don't notify on dispose to avoid exception #38

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open

Don't notify on dispose to avoid exception #38

wants to merge 16 commits into from

Conversation

percula
Copy link

@percula percula commented Jan 3, 2021

I was encountering the following exception everytime a Confetti widget was disposed:

════════ Exception caught by foundation library ════════════════════════════════════════════════════
The following assertion was thrown while dispatching notifications for ConfettiController:
setState() or markNeedsBuild() called when widget tree was locked.

This _InheritedProviderScope<ConfettiController> widget cannot be marked as needing to build because the framework is locked.
The widget on which setState() or markNeedsBuild() was called was: _InheritedProviderScope<ConfettiController>
  value: Instance of 'ConfettiController'
  listening to value
When the exception was thrown, this was the stack: 
#0      Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:4297:9)
#1      Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:4307:6)
#2      _InheritedProviderScopeElement.markNeedsNotifyDependents (package:provider/src/inherited_provider.dart:496:5)
#3      ChangeNotifier.notifyListeners (package:flutter/src/foundation/change_notifier.dart:226:25)
#4      ConfettiController.stop (package:confetti/src/confetti.dart:371:7)
...
The ConfettiController sending notification was: Instance of 'ConfettiController'
════════════════════════════════════════════════════════════════════════════════════════════════════

It was being caught by the framework, but started to clog up my logs. Simply avoiding a call to notifyListeners during dispose() fixes the issue.

@funwithflutter
Copy link
Owner

Thanks for the pull request. Do you mind giving an example of when this exception will be thrown. I tried recreating it by replacing the current route while an animation is playing. Dispose is called, and stop is called, but I'm not getting the exception.

@percula
Copy link
Author

percula commented Jan 5, 2021

Yep, I replaced the example in the repo with one that throws the exception. It's on this branch: https://github.com/percula/flutter_confetti/tree/exception_example

Note that I added Provider. Perhaps that's the reason you didn't see it when you tried to replicate it.

@funwithflutter
Copy link
Owner

funwithflutter commented Jan 28, 2021

Ah okay. Because ConfettiController is a ChangeNotifier, and using it with Provider's changenotifier is causing the issue.

I like your suggestion with the pull request and I'll merge it in, but maybe in the future this needs to be refactored to not be a ChangeNotifier. A ValueNotifier might be better. Is there any reason you'd want ConfettiController to remain a ChangeNotifier?

@percula
Copy link
Author

percula commented Jan 28, 2021

Since ValueNotifier is extended from ChangeNotifier, wouldn't we have the same problem?

@funwithflutter
Copy link
Owner

Since ValueNotifier is extended from ChangeNotifier, wouldn't we have the same problem?

Yes. But I'm thinking of making the ConfettiControllerState (an enum with fields playing and stopped) a ValueNotifier, not the ConfettiController class (this would then not extend anything). Because the ChangeNotifier is used just to update that "state" (ConfettiControllerState) within the ConfettiController.

The ConfettiWidget cares about that state and this is an easy change to make, but the problem is that some people may also care about that state change (if they want to know when the state changes, for example playing to stopped). So this might be breaking someones code if they listen to the ChangeNotifier. But it might be better to create a callback within the ConfettiWidget that will be called when the ConfettiControllerState changes, that people can use. Or they can also use the ValueNotifier.

But with this change it would mean you can provide the ConfettiController using a normal Provider (not ChangeNotifierProvider).

@shinriyo
Copy link
Contributor

@percula Can you resolve?

@shinriyo
Copy link
Contributor

shinriyo commented Jul 3, 2024

@funwithflutter

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.

5 participants