For example, when the widget first displays I pull the data and display it. Then a user edits or deletes something and I need to grab the data again and refresh the screen.
If all I needed to do was the initial data pull, then I know I can use FutureBuilder. But since I need to pull the data again and again, I don’t think FutureBuilder will work.
Can I just use setState, initState and some sort of updateState method?
Is StreamBuilder the correct way to go?
A StreamBuilder or ValueListenableBuilder is a possibility. I recommend looking into State Management solutions like my package watch_it with get_it to get an easy approach.
Gotta say it again. Riverpod.
3 Likes
-
Don’t overcomplicate with state managements (especially Riverpod. That sucks, a lot).
-
There are a lot of ways to make something trigger a rebuild:
a) ValueNotifier: It’s a variable with a .value
of type T
. You use ValueListenableBuilder
and set that notifier. Whenever the .value
changes, your ValueListenableBuilder.build
method triggers.
b) ChangeNotifier: it’s like the above, but it is not automatic. It will notify when you call the notifyListeners()
method. That means that you can put a lot of values inside a class that inherits ChangeNotifier
, along with methods (so, let’s say: a bool for userIsAuthenticated
, a User
for authenticatedUser
, a method signIn()
to sign in the user, etc. You listen to those changes using ListenableBuilder
(whenever your ChangeNotifier.notifyListeners()
is called, the ListenableBuilder.build
is triggered.
c) setState
is very underestimated. It has a huge advantage that your widget will hold a copy of the state (and that will not be lost when you hot reload your app!). You could use any other method described here to change a local variable using setState
(for example: initState()
register a Stream
listener, dispose()
unregister it, your listener call setState
with the value received, copying into a local variable). Hot reload state is maintained that way.
d) Stream
and StreamBuilder
: that is VERY powerful. Works with both streams (StreamController), that is kinda like a socket: you emit values into it, your StreamBuilder rebuilds. Also accepts generator functions (a function where each yield
is a new value pushed to the stream), basically, it makes a method be the source of the stream values (for example, when you are doing authentication, you can yield ImBusingWaitingForGoogle;
, then auth with google, then yield thatWorkedImSendingInfoToTheBackend;
, do some stuff on your back end and then finally yield authenticationSuccessful;
. Each yield will be added to the stream (and also all exceptions thrown). A good way to make a method that do a lot of steps maintain a state.
b) is basically a copy of WPF ChangeNotifier, the thing that makes WPF data binding and had originated the MVVM architecture.
All those options are available in Dart/Flutter, so no external dependencies. Also, you don’t need to learn anything to use them.
3 Likes
I used StreamBuilder with a StreamController, it’s easy to use and works great.
It’s how I started after I wrote get_it to access the objects that held the streams.