Reputation: 2771
I have created a simple Widget Tree of my app in flutter that adresses the issue.
The issue is that when I call the method in my SleepSessionData
which is a ChangeNotifier
class, the consumer does not get fired.
There is no issue if the method containing notifyListeners()
is called within the same widget, but when it is two sibling widgets the consumer does not update unless a setState
is called.
And a image of the screen for reference
SleepSessionData extends ChangeNotifier
void updateSelectedPlaylists(List<String> selectedPlaylists) {
this.selectedPlaylists = selectedPlaylists;
notifyListeners();
_saveData();
}
PlaylistSelectorWidget
void selectedIndex(int index) {
...
context.read<SleepSessionData>().updateSelectedPlaylists(_selectedPlaylistIds);
setState(() {});
}
In my SettingsWidget
I tried using both Consumer
Widget and and watch()
method. But it is as the notifyListeners()
does not trigger the consumer/watcher. If i run a setState()
(triggered by user input) the value from the the ChangeNotifier
updates.
Here's my MultiProvider
in main.dart
child: MultiProvider(
providers: [
ChangeNotifierProvider<MySleepData>(create: (_) => MySleepData()),
ChangeNotifierProvider<DirectoryData>(create: (_) => DirectoryData()),
FutureProvider<UserData>(
create: (_) => LocalPersistence.getUserData(),
initialData: UserData()),
FutureProvider<SleepSessionData>(
create: (_) => LocalPersistence.getSleepSessionData(),
initialData: SleepSessionData(),
)
],
Upvotes: 3
Views: 6492
Reputation: 688
You shouldn't wrap your ChangeNotifier
inside the FutureProvider
in order to make it works properly.
When you wrap the ChangeNotifier
inside the FutureProvider
it breaks the process of adding listeners to the ChangeNotifiers
somehow. You always get 0 listeners when wrapping ChangeNotifier
with FutureProvider
. (You can verify this by debugging and check the listeners
property of your ChangeNotifier
instance.) That's why when calling notifyListeners()
, the widgets don't rerender since they're not the listener of your ChangeNotifier
instance.
So the solution to your problem would be:
ChangeNotifier
in main.dart
child: MultiProvider(
providers: [
ChangeNotifierProvider<MySleepData>(create: (_) => MySleepData()),
ChangeNotifierProvider<DirectoryData>(create: (_) => DirectoryData()),
ChangeNotifierProvider<UserData>(create: (_) => UserData()),
ChangeNotifierProvider<SleepSessionData>(create: (_) => SleepSessionData()),
],
SessionSetupPage
, you get the data from your local store and load the changes to SleepSessionData
loadData(SleepSessionData sessionData) async {
final data = await LocalPersistence.getData();
sessionData.setData(data);
}
Widget build(BuildContext context) {
loadData(context.read<SleepSessionData>());
// ..
}
PlaylistSelector
and SettingsWidget
should work whenever notifyListeners()
is called since the listeners are bound correctly now.so when the future completes it will overwrite this value
This is not totally the root cause of the issue though. Even if we create the SleepSessionData
instance beforehand and return the same instance inside the FutureProvider
, the problem still persists.
Upvotes: 3
Reputation: 5648
You only have a FutureProvider
that holds the SleepSessionData
so that will only update once when the future completes.
If you want the ui to update on changes of the result of the future then you need to listen to those changes, for instance by using a ChangeNotifierProvider
.
Additionally you are giving the FutureProvider
an initial data with a new instance of your SleepSessionData
so when the future completes it will overwrite this value meaning that any actions you do on the initial value will be discarded.
So a better way of doing this would be to not use a FutureProvider
but use a ChangeNotifierProvider
and start the future to load the data within your SleepSessionData
class.
Upvotes: 0