Caching Data ( Redundant API Calls ) - flutter

I'm new to Flutter, and I've stumbled upon a problem I need advice in how to approach it. I'm building an app which uses navigator and flutter_bloc. Now when I navigate to a certain route I have the bloc state pull some data from an API and show it. What I want to achieve is not call the API every time when I navigate to that route unless the app has been closed previously or a "pull to refresh" action has been made. How do I got about storing the data after the initial API call. I've tried with the hydrated_bloc but either I don't understand the point of the hydrated_bloc well or it's intention is not to do that. Thank you for the advice in advance.

class AppState {
static final AppState _instance = AppState._internal();
factory AppState() => _instance;
ApiResponseCustomClass apiResponse;
AppState._internal() {
// init things here if needed
}
}
A simple way is to just make a state class where you will keep the result in, and then access it via AppState().apiResponse anywhere in your code.

You can use local_storage to maintain your data locally. So every time you need to fetch data from API again and again. and you can clear data before closing the app.

Related

Can i call cubit from another cubit?

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

ChangeNotifier wrap class around each instance of a model

I have an application where I display a list of cards that represent a model (Let's say a Person). These are stateless widgets as they cannot be changed directly. These instances are obtained from an API and, since the amount of items is large, I am using AutomaticKeepAliveClientMixin to keep them from reloading and triggering more API calls.
When clicked, these cards lead to the Person's page where there we can edit some information on them. Using a StatefullWidget here with setState takes care of all issues related to the page. However, when I pop the individual page the card that was clicked does not reflect the changes made.
I was thinking of writing a ChangeNotifier wrapper for each Person but from what I've read this is a bad idea. Using more powerful state management tools like BLoC or Redux seems like overkill too. How can I implement this properly?
I think you should try:
ontap: () async {
await Navigator.push ....);
ref
}

Can iOS14 widget requests main app to update its data?

my app needs latest data but, possibly, the main app has old data.
so i want to request to the main app to update its data.
is it possible?
if it is not I would like to know any alternative way.
(should the widget requests latest data to the server??)
thanks
===
UPDATE
I found many tutorials and all of them use http request from getTimeline method for getting newest data (not from the main app). it is not what i want.
Someone said easest way for sharing data between main app and widgets is using UserDefaults. But the data can be old if the main app does not update userdefaults values or update values using old data. (beside server data is always latest data)
So what i want to know is the way 'widget makes main app updates its data and updates userdefault and call reloadTimelines. so widget can use latest data.
There's no way for a Widget to tell its parent App to refresh its data.
You can either:
fetch data directly in the Widget - see: How to refresh Widget data?
enable background notifications in the App (see How to run code when your app is terminated) and, when received one, force the Widget to refresh its timeline using:
WidgetCenter.shared.reloadAllTimelines()
In reality it's probably better to just fetch data directly in the Widget. This way you can fetch only the necessary data - Widget views usually display a lot less information than App views.
Yes, you can like this;
When you create a TimelineProvider for widget update, you have to implement this func,
func getTimeline(in context: Context, completion: #escaping (Timeline<Entry>) -> ())
This function waits to create your widget update timeline. You can sen a request, after the response, you can create a timeline and return func's completion.
You can configure an App Group and store the database in that shared group directory. That way, if you update data in the main app or in the widget, those new data are available for both, it's not necessary to call the other one to load the same data again. Just be aware that you should still use
WidgetCenter.shared.reloadAllTimelines()
after you updated the data in your main app to refresh the widget immediately. Just have some handling for when the last request was performed, so you don't create an unnecessary request in your widget, and instead fetch them from the database.
If you move your request-performing code into a modul, you can also use it in the widget, as you do in your app. Finally you'll just have another call of the same updating code you are used to from your main app.
Since I don't have any of your code to update and present here, I'll just link some helpful sources for the way to the described destination.
Apple Documentation: Configuring App-Groups
Sharing data within App-Groups

Flutter count number of page view and show it

I want to implement the number of views feature in my application with flutter.
The feature is the same as StackOverflow question view counter: it's persisted.
I was thinking of firebase analytics but I think it's not free to get data from there
Is there any way to do it?
Thanks in advance
The previous answer is correct but you should know it's not free.
The way I found to return analytics data is to use BigQuery which is in the BLAZE plan so I think you have to pay to get data from firebase analytics
To calculate the number of views in my recent app i used Firestore, which is Firebase's Database. Initialize the views as zero in your database and then write a function to increment the view every time the user views it.
How do you determine if the user viewed it?
Now that entirely depends on your application.
There is a short way instead if you just want to capture number of visitors on your webapp
I created a collection called "Visits" in firestore and generated auto id inside which I added a field called "count". That's it! Now you just have to call this method in your first screen's init method :
updateCounter() async {
final cRef = FirebaseFirestore.instance.collection('VISITS');
await cRef
.doc("mS9fCXjvkpREt8LvanSb")
.set({"count": FieldValue.increment(1)}, SetOptions(merge: true));
}

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.