Caching with Dio + Hive in Flutter

Aravind Chowdary
4 min readSep 20, 2022

--

Caching basically is the process of storing the response from a request on device storage to avoid frequent network requests to the API or any other resource on the internet.

You might already use CachedNetworkImage in flutter to avoid multiple network requests for loading images in your flutter app. This helps user by saving the mobile data and also reduces the requests made to your server for the same resource which was loaded before.

We can do this for API calls in our app too. If you followed any other articles on the internet, they usually show you with the MemCacheStore as the caching store. But the problem with this is that the MemCache will be cleared when you quit the app. If you want to cache the response and preserve it on the app reopen then this is the guide for you.

In this we’ll use Hive as our cache store, Hive is a lightweight and blazing fast key-value database written in pure Dart. We can use hive as our cache by using the network request uri as key and the response provided by the request as the value.

Interested in Flutter Dev ? checkout various other flutter related guides on FlutterDevExperts

Implementation

Add the required packages to the pubspec.yaml file in your project.

hive: ^2.0.5dio: ^4.0.6
dio_cache_interceptor: ^3.3.0
dio_cache_interceptor_hive_store: ^3.2.0

The first line imports the hive library and the other three are the dio and dio interceptor packages that we’ll use to intercept the requests made using dio and capture the data to cache.

Cache Dir

The folder where you want to store the data that is being cached by the api calls. To follow the best practices we’ll use the flutter provided method to get the temporary folder of the device.

var cacheDir = await getTemporaryDirectory();

This above line will get the temporary directory object which we can use to direct the hive to store the cache in this folder.

If you want to, you can also make a custom path to the folder which your app has access, but I don’t recommend that as it might eat up user’s storage and they can’t clear cache from the app settings unless you provide a way to.

build Cache Store

Now we’ll make a cacheStore object which we need to pass to the cache interceptor to indicate the cache references.

var cacheStore = HiveCacheStore(
cacheDir.path,
hiveBoxName: "your_app_name",
);

The above HiveCacheStore takes two arguments, cacheDirPath(string) and the hiveBoxName(string) which can be anything you want.

CacheOptions

We have cacheStore object we created in the above step, we use that to make a cacheOptions object for the interceptor which tells it how to manage the cache.

var customCacheOptions = CacheOptions(
store: cacheStore,
policy: CachePolicy.forceCache,
priority: CachePriority.high,
maxStale: const Duration(minutes: 5),
hitCacheOnErrorExcept: [401, 404],
keyBuilder: (request) {
return request.uri.toString();
},
allowPostMethod: false,
);

For the cacheOptions object we pass the cacheStore, policy, priority, staleDuration, keyBuilder and others. Let me explain

  • CachePolicy

CachePolicy.forceCacheyou’ll save every successful GET requests.

CachePolicy.refreshForceCachewhen origin server has no cache config, Requests regardless cache availability, Caches if response has cache directives.

CachePolicy.refreshRequests regardless cache availability, Caches if response has cache directives.

CachePolicy.noCacheRequests and skips cache save even if response has cache directives.

  • Priority

This just tells how much priority must be given to the cache over network data.

high , low and normal

  • MaxStale

Here you set the duration about how long should your cache should stay live.

  • KeyBuilder

The returned string of this method is used as the key for the cache in the cacheStore, make sure it’s unique for each request other wise your cache might corrupt the data received on a different api call.

  • AllowPostMethod

This argument just tells the interceptor if it should also cache the post method responses which aren’t usually cached.

Building Dio

Finally we build dio object and pass in the configured cache options and the cache interceptor for caching the request made through this dio object.

var customDio = Dio()
..interceptors.add(DioCacheInterceptor(options: customCacheOptions));

And that’s it.

Interested in Flutter Dev ? checkout various other flutter related guides on www.aravi.me

Now all your get requests made on the dio object we created above will be cached to the user’s device storage temp dir.

Now, your API won't call the server every second and eat up your cloud resources.

Leave a clap if this helped you, comment if you have any issues. Thanks!

--

--