When do I use setState in Flutter?
According to the docs:
Calling setState notifies the framework that the internal state of this object has changed in a way that might impact the user interface in this subtree, which causes the framework to schedule a build for this State object.
So if the state of the widget changes you have to call setState
to trigger a rebuild of the view and see immediatly the changes implied by the new state.
Anyhow the below snippets are equivalent.
first case (directly form flutter create <myproject>
):
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
second case:
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
_counter++;
setState(() {});
}
What I don't know is the reason why and if the first case is the conventional way to use setState
, I would say because of readability of code.
Flutter: Why setState(( ) { }) set data again and again
The purpose of setState
is to tell the framework that a variable in the state has changed and the widget needs to be rebuilt to reflect that change. So calling setState
calls the build
function again, which in your case recalls your Future
, which calls setState
again, which triggers build
and so on.
To fix this you should call the Future
in initState
, and use a FutureBuilder
to display the data when it's ready.
Example:
class _SampleState extends State<Sample> {
Firestore db = Firestore.instance;
Future databaseFuture;
@override
void initState() {
databaseFuture = db.collection('share').document('0').get()
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: databaseFuture,
builder: (context, snapshot) {
if(!snapshot.hasData) {
return CircularProgressIndicator();
}
var message = snapshot.data.data['message'];
print(message);
var appLink = snapshot.data.data['appLink'];
return Text('$message $appLink');
}
),
}
}
Need explanation for setState() function in Flutter
You'll find the answer in the official docs:
The provided callback is immediately called synchronously. [...] If you just change the state directly without calling setState, the framework might not schedule a build and the user interface for this subtree might not be updated to reflect the new state.
I think the problem is that UI and state object will not be in sync for a short period of time if you call setState((){});
after changing the state.
Flutter setState Function
No. setState by design is rebuilding all widgets that depend on the state on which the method os being called.
If you refactor your monolithic widget into sub-widgets, you can have finer-grain control over what gets rebuilt. Also, you should look into a state management solution like RiverPod to be able to narrow down "consumers" to be associated with their triggers, which helps tremendously.
Also, if your build is expensive, you are doing something wrong. A build should be cheap, capable of being performed 60 times per second with no I/O or expensive calculations.
Should you use setState when having RiverPod
Yes you can. You need to understand there are 2 types of state:
Ephemeral(Local): This is contained to only a single widget and not used for passing information between different components. You should use
setState
and internal state variables for cases like these. Like @Ruchit said in his comment above, a good example is a checkbox, switch, dropdown. Or if you want to hide/show something based on some data.Global: This is for any information that is passed between layers, components or widgets and should be accessible and synced across different screens. For these cases you should use state management solutions like
Provider
,Riverpod
etc. Some examples are:- Adding items to a cart.
- Updating a favourites list.
- Sending data to network layer to make http calls etc.
Related Topics
How to Solve Render Problem Path.Op() Not Supported
Couldn't Get Connection Factory Client - Fighting with Google Maps
Gridlayoutmanager - How to Auto Fit Columns
Change Chip Widget Style Programmatically Not Working - Android
Widgets Don't Respond When Re-Added Through Code
How to Add Firebase-Admin to My Android Project
Cordova Cannot Add Android Failed with Exit Code Enoent
How to Bring a Background Task to The Front Below Honeycomb
How to Style Appcompat-V7 Toolbar Like Theme.Appcompat.Light.Darkactionbar
Bypass Android's Hidden API Restrictions
Obtain Root Access via Su on the Android Emulator
Android Studio - Cannot Resolve Symbol 'Firebase'
Android Studio: Exclude Resource File Under Resources Sourcesets
Android Stream Video from Google Drive
Import .R Cannot Be Resolved When I Import Actionbarsherlock