-2

what I'm trying to achieve here is a functionality that firstly tries to load the data stored in local storage (if any) and then fetch the new data from the API and displays and stores them in local storage.

I'm thinking of two ways to do that but since I'm not familiar with Flutter, I actually don't know how exactly to do that.

Imagine doing that in React Js/Native:

First Way

  1. use a state hook to store the data
  2. display an activity indicator if state is null/empty
  3. read the data from storage and display them to user
  4. fetch the new data, update the state and store the new data in local storage

Second Way

  1. use a state hook to store the data
  2. display an activity indicator if state is null/empty
  3. read the data from storage and display them to user
  4. re-read the data from storage while listening to a event listener (the event emits from an another file after data gets updated and stored on local storage)

I know a few things about FutureBuilder() in flutter and using it to fetch the data and then display them but I was wondering how to achieve this functionality in Flutter.

Davis
  • 1,219
  • 2
  • 8
  • 17

1 Answers1

0

To achieve your goal i would use FutureBuilder mixed with some custom logic.

For example i would use localstorage package to store and retrieve data from localStorage.

I would create 2 methods.

  • One for fetching your service and update the localStorage
  • The other to retrive the localStorage cache

Then in you component, fetch the service, but in the meanwhile, show the cached data if present.


So you could do something like this in your Service class (I will refer to this as OurService in the next snippet)

import 'package:localstorage/localstorage.dart';

...

final LocalStorage storage = new LocalStorage('my_app');

Future fetchData() async {
      // Fetch your service
      final response = await callYourService();
      // Set your cache
      storage.setItem('someSpecificDataKey', response)
      return Future.value(response);
}

SomeType? getLocalData() async {
   final cacheData = storage.getItem('someSpecificDataKey')
   if (cacheData != null) {
      // Return cached data
      return cacheData;
   } return null;
}

and then in your Widget do something like

OurService service = OurService(); // this refer to the above snippet
late SomeType? localData;

@override
void initState() {
    super.initState();
    // Get the cache value (possibly null)
    localData = service.getLocalData();
}


Widget build(context) {
  return FutureBuilder<dynamic>(
      future: service.fetchData(), // Fetch the service
      builder:  (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            // Render the latest fetched value (When the fetch is complete)
          }
          if (localData != null) {
              // While the fetch is still resolving
              // here you can render something using `localData`
          }
          // Render something when you have no `localData` and the fetch is still running      
      }
  )
}

Then if you need to fetch again your service, simply call setState() in this component, will re-fetch the service and will show the last cached value in the meanwhile.

Calling setState() will create a new Future so the process will start again as in the beginning.

I think this is may be a good starting point to solve your needs :)

Doc
  • 655
  • 4
  • 11
  • 1
    However one important thing is missing. How to update the data being shown? As I mentioned I would like to display the locally stored data first (if exists) and then call the api and update the stored and shown data. Do you have any idea? :) – MohammadMahdiRafiei Jun 29 '22 at 16:03
  • I updated my post changing the behavior! This should do the trick :) Take a look again – Doc Jun 29 '22 at 16:29
  • Thank you so much Francesco for investing so much time and effort in my question. – MohammadMahdiRafiei Jul 09 '22 at 13:26