I've tried several and will share what I came up with.
I ran into the same issue mentioned in the question, I'll explain it again now.
This is my ChangeNotifierProxyProvider code:
ChangeNotifierProxyProvider<ProfileProvider, SplashProvider>(
create: (context) => SplashProvider(splashRepo: SplashRepo(), profileProvider: ProfileProvider()),
update: (context, profileProvider, _) => SplashProvider(splashRepo: SplashRepo(), profileProvider: profileProvider),
),
And when I execute the notifyListeners();
function from SplashProvider
, the same error mentioned in the question pops up
Unhandled Exception: A SplashProvider was used after being disposed.
So the logical solution is to move the Provider above MaterialApp/Navigator as mentioned in this issue.
However my code is actually written this way! So how does this error appear?
I don't understand why SplashProvider is being disposed? I did not even disposed my current screen yet!
So I've tried the following:
- change SplashProvider constructor from
SplashProvider({
required this.splashRepo,
required this.profileProvider,
})
to:
SplashProvider({
required this.splashRepo,
required this.profileProvider,
}) {
debugPrint('SplashProvider constructor');
}
To keep track of the number of objects being created from the same provider
It turned out that more than one instance was created, and this is the output:
I/flutter ( 5370): SplashProvider constructor
I/flutter ( 5370): SplashProvider constructor
I/flutter ( 5370): SplashProvider constructor
So I modified the constructor by adding message
:
final SplashRepo splashRepo;
ProfileProvider? profileProvider;
+ final String? message;
SplashProvider({
required this.splashRepo,
this.profileProvider,
+ this.message,
}) {
debugPrint('SplashProvider constructor: $message');
}
Then changed ChangeNotifierProxyProvider
by adding message
to distinguish each of them:
ChangeNotifierProxyProvider<ProfileProvider, SplashProvider>(
create: (context) => SplashProvider(message: 'create', splashRepo: SplashRepo(), profileProvider: ProfileProvider()),
update: (context, profileProvider, _) => SplashProvider(message: 'update', splashRepo: SplashRepo(), profileProvider: profileProvider),
),
Then I wrote these two commands into SplashProvider
to track if the provider was disposed
or not, and also when notifyListeners
was called, and for which object in them.
@override
void dispose() {
debugPrint('SplashProvider disposed...[$message]');
super.dispose();
}
@override
void notifyListeners() {
debugPrint('notifyListeners in splash: [$message]');
super.notifyListeners();
}
And this is the output:
...
I/flutter ( 5370): SplashProvider constructor: create
I/flutter ( 5370): SplashProvider constructor: update
I/flutter ( 5370): notifyListeners in splash: [update]
...
I/flutter ( 5370): SplashProvider constructor: update
I/flutter ( 5370): SplashProvider disposed...[update]
I/flutter ( 5370): [ Easy Localization] [DEBUG] Build
...
I/flutter ( 5370): notifyListeners in splash: [update]
E/flutter ( 5370): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: A SplashProvider was used after being disposed.
E/flutter ( 5370): Once you have called dispose() on a SplashProvider, it can no longer be used.
...
So it tries to call notifyListeners
in the updated instance which had disposed already!
then it throws that error
To solve this problem I tried changing the main ChangeNotifierProxyProvider command to:
ChangeNotifierProxyProvider<ProfileProvider, SplashProvider>(
create: // same code...,
update: (context, profileProvider, prev) => prev!..setProfileProvider(profileProvider),
),
And surely added this function in SplashProvider
:
void setProfileProvider(ProfileProvider profile){
this.profileProvider = profile;
}
to set profileProvider.
Upon trying more than once, the problem was actually solved.
1. The error never appears again.
2. SplashProvider is not disposed.
3. Only one Provider instance is created.
But I don't know yet if this will affect the other Provider that I passed to SplashProvider and will it pass the same instance or will it create a new instance?
I will experiment and if there is something unexpected I will amend my comment.