So what is the simplest approach for Caching in Flutter?
After experiencing many solutions for caching, here is what I’ve learned sorted by complexity:
1- using shared preferences 2- using hive db 3- using firestore offline service 4- using sqflite
A simple time-based cache doesn't require much code.
This might help you out. It uses ScopedModel
, but it could just as easily be a simple class, although you'd have to either remove the notifyListeners()
call or replace it with your own mechanism if you want the model to trigger a refresh of the UI.
class MyModel extends Model{
Duration _cacheValidDuration;
DateTime _lastFetchTime;
List<MyRecord> _allRecords;
MyModel(){
_cacheValidDuration = Duration(minutes: 30);
_lastFetchTime = DateTime.fromMillisecondsSinceEpoch(0);
_allRecords = [];
}
/// Refreshes all records from the API, replacing the ones that are in the cache.
/// Notifies listeners if notifyListeners is true.
Future<void> refreshAllRecords(bool notifyListeners) async{
_allRecords = await MyApi.getAllRecords(); // This makes the actual HTTP request
_lastFetchTime = DateTime.now();
if( notifyListeners ) this.notifyListeners();
}
/// If the cache time has expired, or forceRefresh is true, records are refreshed from the API before being returned.
/// Otherwise the cached records are returned.
Future<List<MyRecord>> getAllRecords({bool forceRefresh = false}) async{
bool shouldRefreshFromApi = (null == _allRecords || _allRecords.isEmpty || null == _lastFetchTime || _lastFetchTime.isBefore(DateTime.now().subtract(_cacheValidDuration)) || forceRefresh);
if( shouldRefreshFromApi )
await refreshAllRecords(false);
return _allRecords;
}
}
To get data from MyModel
, the UI simply calls getAllRecords()
. This will either fetch the records from memory (i.e. from _allRecords
) or trigger a refresh which would make a HTTP call and update the records. The cached data automatically expires after 30 minutes, and if you want to force a refresh (for example if the user explicitly taps a refresh button), you can pass forceRefresh: true
.