Flutter is using provider to load data is the right option? - flutter

So i have a situation where i make an request from the server for one widget.
The widget is at the home page, lets take the worst case where the data is huge and the request take time.
Should i change the widget to stateless and make a provider which i will initialize before i run the app with all the initial data?
Should i contain all the data of the widgets at home page and deliver theme as props, i miss understood the concept of managing the state here, I'm coming from vue and i try to write my first app and I'm struggling how to structure my data through the routes.
I would like if some one explain or give a good source that show how to initialize data from third party
before the home page reload.
Which approach is better getting all the app data before the app reload or request data every time from db with cash

You might have seen this approach in other apps as well which is to show a splash screen until the data has been loaded and ready to be shown. This approach is mostly used by apps which got large data to load at the start. You could achieve this in your initState like the following.
#override
void initState() {
loadData();
splashTimer = Timer(Duration(seconds: 4), () {
_goToHome();
});
super.initState();
}

State management in flutter is a topic with hot debate, there is no best approach, but using one for sure is better than nothing. However there are exceptions to this, sometime adding a state management to a simple part of the app is not recommended. Regarding your case, it can be done without a full state management solution, by using a FutureBuilder for example. Or it can be also done with Provider, BloC, Redux...
As a naïve general rule, if the state is to be passed down the widget tree more than 1 or 2 levels, you should probably start looking for a state management solution depending on the use case. As I already have said, there is no one best state management solution.
Also, it is ok to use more than one as long as you know what you are doing but in general as a best practice it is not recommended to use more than one.
Regarding the second part of the question, it totally depends on the nature of the data and it's size. If the data is big and it is a small possibility that the user will be using all of it, it is better to load it on demand, also loading all the data upfront will increase the cost on the backend side.
However getting the data upfront, makes the experience more seamless to the user (Not waiting while using the app, but he will have to wait a little extra when the app is first loading).
So as you see it is a balance. Also it is good for the server and the app to do some type of caching since it helps reduce the work on the server side and decrease the bandwidth usage on the phone.
An example for caching images you can use Cached Network Image Link, example from flutter cookbook Link.

Related

Is it recommended to use Stream Builder for a single data fetched from a database? if so, will it highly affect the performance of my app?

Is there any problem using StreamBuilder for a single set of data that is fetched from database in my app?
Stream builder is to continuously get data. Even if its a single data or multiple entries if the app needs to fetch data continuously then its good to use Stream builder. Btw fetching single entry will not affect the performance of the app to a great extent. So you should be good to go with Stream builder
https://api.flutter.dev/flutter/widgets/StreamBuilder-class.html
In general terms, no, it is not a problem nor does it greatly effect the performance of the app.
But as always, it depends on more factors. Let for instance say you have a ListView with a bunch of Card in it. And in each Card you have 10 Text-widgets. If you now have a StreamBuilder for each of those Text-widget, and each StreamBuilder does separate requests to your database, and each query is timeconsuming... then yes; it is not optimal. But if it in the end will effect the performance is still hard to say. You'd have to test :) Don't optimize before you need to.

Save full state of a Flutter Application

Is there a way to save then restore the full state of a Flutter application ?
By full, I mean saving the states of all widgets and objects
For example, a TextField will have the exact text on it, the exact color, highlights,
A GoogleMap will have the exact Zoom states, Markers, Polylines
Every objects internal states will be kept, even private fields.
...
I can't do it manually for three main reasons:
There are too many states, any wrong state can lead to a butterfly effect of discrepancy
Some states of some classes are impossible to get and set as they are internal (private)
Some states are random at instantiation
I figured out the technical term is https://en.wikipedia.org/wiki/Continuation
There is an important use case for that:
User could Save current state of their work then resume later. (More like "Save" in games)
No, there is no automatism to save "all", because "all" would be impractical and impossible to determine. After all, you don't have endless time or disk space before a mobile operating systems kicks your app out of it's memory, you should not just "dump all" because it might be too much for any real app.
Some good info can be found here:
Flutter app restoration; how to save the app state when the activity is killed by the system?
If you are using the BloC state management approach, it has a package called hydrated_bloc, that basically manages your BloCs storage so it can be restored to it's previous values when you open your app the next time.
Flutter itself seems to have a RestorationManager class to handle this, but it has no automatisms, you need to do that. So all controls or packages you use may not save their state and then you are out of luck and back to the way where you determine what is important and what can be lost.

How to check application state with FlutterDriver?

We're building some integration tests with FlutterDriver, and would like to verify the state of the application.
It seems flutter drive runs in a totally different instance than the app, so they can not communicate indirectly by stashing data in some shared static class.
Are there any common strategies to passing data to the test layer, from the app?
Some ideas I thought of:
We could write json values to disk, but can the test side actually read it?
Have a hidden text widget, that shows a special ui view that renders state so we can then read it from the test layer
fwiw, we have solved this currently by json-encoding some of our app state into an invisible Text widget that we place on screen.
The test can then lookup that text, decode the json, and read the current app state.
Pretty hacky but it works!
test('Check flutter driver health', () async {
Health health = await driver.checkHealth();
print(health.status);
});

Is a Stream<List<Object>> from Firebase snapshot returning the entire node at every change in the node? Flutter

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.

How to make my pages in flutter persistent?

I want to make all my inherited pages persistent using flutter but I don't know how does anyone know how to accomplish this?
Given the fact that this cannot be answered properly without seeing your implementation, here is what a lot of developers do:
If you application is simple, store each state as a key-value pair. Then store that value and key inside shared preferences.
You would simply need to:
Add shared_preferences: "<newest version>" to pubspec.yaml
Synchronously update the key-value pair in-memory using prefs.setInt('currentState', value);. This persists the data to the disk.
Read your state data suing final counter = prefs.getInt('currentState') ?? 0; and accordingly update your setState method:
Now, this does infact assume that you have a simple application with simple states. If you have more complicated states and actions, then you should consider things like the BLOC pattern in order to organize your app in a way that enables a larger amount of control.