I'm somewhat new to flutter and my question is more philosophical. When using setState(), is it bad practice to call it without using new data in the method? Ex: I call it like this:
setState({});
If there's a better way to refresh the build function or is this the best way?
setState notifies that internal state of the object is changed, that reflect on entire subtree.
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.
There are some other ways to trigger build method when data changes, but easiest one is setState() and for your purpose it is best.
No need to use new data in your case. Your way of doing this is exactly how the Flutter team intended it to be used.
Related
I'm new to using the Bloc pattern in Flutter, and I wish to update some widgets (i.e. state) for every bloc concerned by an external change.
For example, imagine that I have a trading application, and so I have a "Trading" component that receive some information updates.
My "Trading" component receive new information, but then how does it transmit the new information to the Bloc and so, how it emits (and update) the widget.
Any idea how I can do this? What is the correct pattern to follow ?
You need to emit the state changes (your trading data here) to your state using a BLoC / Cubit which will then rebuild the UI using BlocBuilder.
i'm working on an application that uses cubits, to manage the state.
Very often when i need to make an api request i need to get my current localization (handle possible exceptions) and then send it to backend. So i guess i should use cubit for the requests and for getting my current localization.
So now my question is how should i handle that? Can i somehow call gpsLocalizationCubit from another cubit? Should i call gpsLocalizationCubit and on success call requestCubit with the use of bloc listener? But then how should i manage loading screen that should be visible for both getting localization and api request?
Another problem is that i have multiple similiar request (that need to use current localization) in single view.
Thanks for the answers :D
I was wondering what is the better option to get documents from firestore.
Should i run the getdocuments in initstate or should I run it as a future builder.
So far these are the pros and cons i have seen.
initstate - if I were to retrieve it initState, then everytime i click on a post to see its details, and when i go back, the initstate runs again, creating more documents read. However, this does help refresh certain values, incase of a user bookmarking a post, that way the bookmark value gets updated, however in the cost of more documents read.
futurebuilder - seems cost efficient in the sense that, when i click on a post and go back, no more documents are retrieved from firestore, however, if i were to bookmark the post in the postdetails page, the value does not get updated. However to work this around, i could just remove the bookmark value in the Post page.
I have however, used the getdocuments in the initstate when i go into the postdetails page by deseralizing it.
Please advise.
Calling getDocuments() is deprecated for get() as per the change log.
I would do one of the following:
If using initState, the easiest way to deal with this is to store a
Future variable in your state. In initState make the API call and
store the Future. You can then pass this Future to FutureBuilder.
Keep using FutureBuilder, then when you edit the data make an async
operation to update the database and after the database is updated
call setState to reflect the changes on the UI.
Use a StreamBuilder, which is similar to FutureBuilder, but instead
of building only once, it rebuilds each time there's a change on the
stream it's attached to. This way you just need to update the
datasource and the widget will update itself with the new data.
So my answer would be it depends on your use case. If your data updates every min/sec while you use the app, it needs updates asynchronously at a certain interval, in that case StreamBuilder is the best option but If your use case is to just get the data, and display it, then you can use FutureBuilder.
I'm starting learning Flutter as I want to port my iOS app to Flutter to also run on Android.
I use Firebase real time database for the back-end and I saw that the firebase_database package should suit my needs, allowing me to use the db I already have.
I'm also learning to use the BLoC pattern but all the bloc tutorials I found are for Firestore and all the Event/State/Bloc/Repository/Streaming is still quite confusing to me right now.
What should be the right implementation of the bloc pattern?
To a basic level I do understand it and I like it very much, but thinking of a way to implement it for my needs is resulting a bit overwhelming.
Following this diagram the 6 connections data flow should be:
(UI -> BLoC) An event will be sent to the bloc.
(BLoC -> Repository) The Bloc maps the event to a Repository method.
(Repository -> Database) The Repository methods are database Create/Update/Delete methods.
(Database -> Repository) The Repository database Read method gets database Data.
(Repository -> BLoC) The return from Repository database Read method takes the Data into BLoC.
(BLoC -> UI) The BlocProvider uses the Data to rebuild the UI.
Now what I'm not sure I figured out is the data going back to the UI.
At step 2 if I map the event to a method that returns the data as a Stream<List<Object>> then via a BlocProvider at step 6 the UI(stateless widget) gets rebuilt accordingly.
Now, as I see it, that would be a lot of unnecessary repeating data downloads if for any change, the whole node gets downloaded, also Google's bills you on downloads.
In the Firebase iOS SDK you can attach observers to a node, so you just get a snapshot with the .childAdded/.childRomovedetc etc, and use it to modify your UI.
To avoid useless downloads and keep my account safe, I'd rather make a query on a node with the keepSynced bool set to true ( https://pub.dev/documentation/firebase_database/latest/firebase_database/Query-class.html ). This should (as the iOS SDK) return at first firing, a snapshot with the whole node and than snapshots with just new/updated/delete when something changes right?
To implement this way instead, should I use a List<Object> that I update manually when getting the snapshot and a stateful widget? This is actually how my iOS app works at the moment.
Thank you very much for the help and sorry for the long question, making the switch from Swift is taking it's time.
Firebase listeners only transfer the minimal amount of data that actually changed at the node being listened to. It does NOT transfer the entire node and all of its children each time anything changes. So, it's not as expensive as you're imagining it to be.
I want to load some data from an SQLite database in my Flutter application and show the results in a ListView. I am currently using a FutureBuilder widget to fetch the data asynchronously from the database and then build the ListView.
However, if I want to do some operations on the data - e.g. modify some information and save it to database - and then show the updated data in the ListView, I think I have to store the data in a local variable first and then call the setState() method to make changes to the data and re-build the page.
Is there any other better/preferred way to achieve the same without using FutureBuilder?
initState gets called when your widget gets initialised for the first time. There you do some initialisation operations.
I think you're right to use FutureBuilder, since your UI gets generated after fetching the data from the Database.
I would do one of the following:
Keep using FutureBuilder, then when you edit the data make an async operation to update the database and after the database is updated call setState to reflect the changes on the UI.
Use a StreamBuilder, which is similar to FutureBuilder, but instead of building only once, it rebuilds each time there's a change on the stream it's attached to. This way you just need to update the datasource and the widget will update itself with the new data.
Talking about the second solution, I cannot go any further since I've never implemented a Stream that would allow to do this (I've always used StreamBuilder it with Firebase streams).
The first solution allows you to update the displayed data without asking again for the entire data set to the database.
I might appreciate some feedback from others regarding the second solution, since I'm not sure about how StreamBuilder manages a change of data.
I'll let you know if I discover more!
https://stackoverflow.com/a/52021385/11252673
build() might be called several times - that's why this kind of initialization goes better on initState.