# flutter_map_cache 2.1.0

A slim yet powerful caching plugin for flutter_map tile layers.
Showing cached metadata; upstream refresh unavailable.



## Installing
```
export PUB_HOSTED_URL=https://pub.mirror.p-hatan.com
flutter pub add 'flutter_map_cache:2.1.0'
```
Published: 2026-04-11T16:57:54.362097Z
Expected archive SHA-256: 4ec2f24db456dddcff3370b73efd7e9b9fddf65b2fb61b76b03185ff2682f026

Available in cache; verification: upstream_checksum
## Direct dependencies
- dio: ^5.2.0+1
- dio_cache_interceptor: ^4.0.0
- flutter: map[sdk:flutter]
- flutter_map: >=6.0.0 <9.0.0

## Package README (untrusted upstream documentation)
# flutter_map_cache

A slim yet powerful caching plugin for flutter_map tile layers.

[![Pub Version](https://img.shields.io/pub/v/flutter_map_cache)](https://pub.dev/packages/flutter_map_cache)
[![likes](https://img.shields.io/pub/likes/flutter_map_cache?logo=flutter)](https://pub.dev/packages/flutter_map_cache)
[![Pub Points](https://img.shields.io/pub/points/flutter_map_cache)](https://pub.dev/packages/flutter_map_cache/score)
[![Pub Downloads](https://img.shields.io/pub/dm/flutter_map_cache)](https://pub.dev/packages/flutter_map_cache)

[![GitHub last commit](https://img.shields.io/github/last-commit/josxha/flutter_map_plugins)](https://github.com/josxha/flutter_map_plugins)
[![stars](https://badgen.net/github/stars/josxha/flutter_map_plugins?label=stars&color=green&icon=github)](https://github.com/josxha/flutter_map_plugins/stargazers)
[![GitHub issues](https://img.shields.io/github/issues/josxha/flutter_map_plugins)](https://github.com/josxha/flutter_map_plugins/issues)
[![codecov](https://codecov.io/gh/josxha/flutter_map_plugins/graph/badge.svg?token=5045489G7X)](https://codecov.io/gh/josxha/flutter_map_plugins)

## Motivation

- Many tile providers **require users in their tile usage policy** to cache
  tile requests. This decreases the load on those servers and is important
  especially if they are donation based like the OpenStreetMap.
- Commercial tile providers normally charge per tile request. By caching tiles
  you can reduce the amount of tile requests and **lower your costs**.
- Caching map tiles provides a **better user experience** since the region the
  user visited **loads nearby instantly**. Most of the time a user visits the
  same regions often, e.g. because it is the region he lives in.
- Especially raster tiles that are used by default on flutter_map, the data
  consumption can be high quite fast. Caching tiles **lowers the amount of used
  mobile data and bandwidth**.

flutter_map introduced a caching mechanism in version 8.2.0 that solves these
topics. This package is for users that need advanced use cases that are not
covered by the default caching mechanism of flutter_map and legacy support for
flutter_map versions < 8.2.0.

## Features

The package uses [dio](https://pub.dev/packages/dio) with the
[dio_cache_interceptor](https://pub.dev/packages/dio_cache_interceptor) package
and supports the storage backend that
you like.

Supported storage backends are:

| Storage backend                                 | Description                                                                                                    |
|-------------------------------------------------|----------------------------------------------------------------------------------------------------------------|
| In-Memory                                       | - For testing purposes<br/>- `flutter_map` has memory caching itself                                           |
| File System                                     | - Easy to setup, no additional storage backend package required<br/>- potentially slower than using a database |
| [Drift](https://pub.dev/packages/drift)         | - SQLite database<br/>- good platform support                                                                  |
| [Hive CE](https://pub.dev/packages/hive_ce)     | - key-value database<br/>- easy to integrate                                                                   |
| [ObjectBox](https://pub.dev/packages/objectbox) | - NoSQL database<br/>- More complex integration                                                                |
| [Isar](https://pub.dev/packages/isar)           | - NoSQL database<br/>- More complex integration                                                                |
| [Sembast](https://pub.dev/packages/sembast)     | - NoSQL database                                                                                               |

Other storage backends will be supported as soon as the underlying package
[dio_cache_interceptor](https://pub.dev/packages/dio_cache_interceptor) supports
them.

## Getting started

1. Add the packages you want to use to your `pubspec.yaml` file. Only add the
   packages for the backend you want to use.

```yaml
dependencies:
  flutter_map: ^8.1.1 # in case you don't have it yet 
  flutter_map_cache: ^2.0.0 # this package
  path_provider: ^2.1.2 # in case the storage backend requires a path

  # drift
  http_cache_drift_store: ^7.0.0
  sqlite3_flutter_libs: ^0.5.15

  # file system
  http_cache_file_store: ^2.0.0

  # hive
  http_cache_hive_store: ^5.0.0

  # objectbox
  http_cache_objectbox_store: ^2.0.0
  objectbox_flutter_libs: ^1.4.1

  # isar
  http_cache_isar_store: ^2.0.0
  isar: ^3.1.0+1
  isar_flutter_libs: ^3.1.0+1

  # sembast
  http_cache_sembast_store: ^1.0.0
  sembast: ^3.8.4+1
  sembast_web: ^2.4.1
```

2. ⚠️ Some storage backends have their own required setups. Please check them
   out in their package documentations.

## Usage

Using the cache is easy. Here are examples how to use some of the storage
backends:

### Hive

<details open>
  <summary>Click here to expand / hide.</summary>

1. First get the cache directory of the app (i.e. with
   the [path_provider](https://pub.dev/packages/path_provider)
   package).

```dart
import 'package:path_provider/path_provider.dart';

Future<String> getPath() async {
  final cacheDirectory = await getTemporaryDirectory();
  return cacheDirectory.path;
}
```

2. Then use the directory path to initialize the `HiveCacheStore`. You can wrap
   FlutterMap inside a `FutureBuilder` to use
   the `getPath()` method.

```dart
@override
Widget build(BuildContext context) {
  return FlutterMap(
    options: MapOptions(),
    children: [
      TileLayer(
        urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
        tileProvider: CachedTileProvider(
          // maxStale keeps the tile cached for the given Duration and 
          // tries to revalidate the next time it gets requested
          maxStale: const Duration(days: 30),
          store: HiveCacheStore(
            path,
            hiveBoxName: 'HiveCacheStore',
          ),
        ),
      ),
    ],
  );
}
```

---
</details>

### In Memory (for testing)

<details>
  <summary>Click here to expand / hide.</summary>

```dart
import 'package:dio_cache_interceptor/dio_cache_interceptor.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_map_cache/flutter_map_cache.dart';

class MyMap extends StatelessWidget {
  MyMap({super.key});

  // create the cache store as a field variable
  final _cacheStore = MemCacheStore();

  @override
  Widget build(BuildContext context) {
    return FlutterMap(
      options: MapOptions(),
      children: [
        TileLayer(
          urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
          tileProvider: CachedTileProvider(
            // use the store for your CachedTileProvider instance
            store: _cacheStore,
          ),
        ),
      ],
    );
  }
}
```

---
</details>

### File System

<details>
  <summary>Click here to expand / hide.</summary>

```dart
import 'dart:io';

import 'package:dio_cache_interceptor/dio_cache_interceptor.dart';
import 'package:http_cache_file_store/http_cache_file_store.dart';
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_map_cache/flutter_map_cache.dart';
import 'package:path_provider/path_provider.dart';

class MyMap extends StatefulWidget {
  const MyMap({super.key});

  @override
  State<MyMap> createState() => _MyMapState();
}

class _MyMapState extends State<MyMap> {
  // create the cache store as a field variable
  final Future<CacheStore> _cacheStoreFuture = _getCacheStore();

  /// Get the CacheStore as a Future. This method needs to be static so that it
  /// can be used to initialize a field variable.
  static Future<CacheStore> _getCacheStore() async {
    final dir = await getTemporaryDirectory();
    // Note, that Platform.pathSeparator from dart:io does not work on web,
    // import it from dart:html instead.
    return FileCacheStore('${dir.path}${Platform.pathSeparator}MapTiles');
  }

  @override
  Widget build(BuildContext context) {
    // show a loading screen when _cacheStore hasn't been set yet
    return FutureBuilder<CacheStore>(
      future: _cacheStoreFuture,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          final cacheStore = snapshot.data!;
          return FlutterMap(
            options: MapOptions(),
            children: [
              TileLayer(
                urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
                tileProvider: CachedTileProvider(
                  // use the store for your CachedTileProvider instance
                  store: cacheStore,
                ),
              ),
            ],
          );
        }
        if (snapshot.hasError) {
          return Center(child: Text(snapshot.error.toString()));
        }
        return const Center(child: CircularProgressIndicator());
      },
    );
  }
}
```

---
</details>

### More examples

You can find additional example implementations for other storage backends in
[the example app](https://github.com/josxha/flutter_map_plugins/tree/main/example)
on GitHub.

## Common use cases & frequent questions

### How about web?

<details>
  <summary>Click here to expand / hide.</summary>

This package supports the web as long as you use a storage backend that supports
web.

- In Memory works out of the box
- Hive uses for its web support IndexedDB under the hood to support web.
- Drift (SqLite)
  requires [additional setup steps for web](https://drift.simonbinder.eu/web/)

---
</details>

### Does this package support cancellation of tile requests?

<details>
  <summary>Click here to expand / hide.</summary>

Yes. This package includes the tile cancellation out of the box.
There is no need
for [flutter_map_cancellable_tile_provider](https://pub.dev/packages/flutter_map_cancellable_tile_provider/)
when using
this package.

---
</details>

### Remove the api key from the url before it gets used for caching

<details>
  <summary>Click here to expand / hide.</summary>

Commercial tile providers often use an api key that is attached as a parameter
to the url. While this shouldn't be a problem when the api key stays the same
you might want to make it immune to api key changes anyway.

```
final _uuid = Uuid();

CachedTileProvider(
  keyBuilder: (request) {
    return _uuid.v5(
      Uuid.NAMESPACE_URL,
      request.uri.replace(queryParameters: {}).toString(),
    );
  },
),
```

---
</details>

### Can I use this package for an offline map?

<details>
  <summary>Click here to expand / hide.</summary>

This package does not provide support to download tiles automatically.
Only tiles that were previously visited with an active internet connection
show up on the map.

If you need to have the map completely offline, I recommend to check out
the file formats MBTiles or PMTiles.

---
</details>

### What if I want to use sqflite?

<details>
  <summary>Click here to expand / hide.</summary>

Because [dio_cache_interceptor](https://github.com/llfbandit/dio_cache_interceptor)
already supports Drift as a SQLite solution it's unlikely that `sqflite` will
be supported any day soon.

If you still are required to use only sqflite, I recommend to create your own
tile provider by using the
[cached_network_image](https://pub.dev/packages/cached_network_image) package.

---
</details>

## Additional information

Pull requests are welcome. If you want to add support for another storage
backend you can check out
[dio_cache_interceptor](https://github.com/llfbandit/dio_cache_interceptor).

If you need help you
can [open an issue](https://github.com/josxha/flutter_map_plugins/issues/new/choose)
or join
the [`flutter_map` discord server](https://discord.gg/BwpEsjqMAH).

## Changelog
## [2.1.0] 2026-04-11

- Add `headers` parameter to `CachedTileProvider` to allow adding custom
  headers to tile requests.

## [2.0.0+1] 2025-04-18

- Update "Getting started" documentation

## [2.0.0] 2025-04-06

- Use
  [dio_cache_interceptor: ^4.0.0](https://pub.dev/packages/dio_cache_interceptor/changelog#400)
- Remove deprecated `dioOptions` parameter
- Add
  [hitCacheOnNetworkFailure](https://pub.dev/documentation/dio_cache_interceptor/latest/dio_cache_interceptor/CacheOptions/hitCacheOnNetworkFailure.html)
- Remove `hitCacheOnErrorExcept` in favor of the
  new [hitCacheOnErrorCodes](https://pub.dev/documentation/dio_cache_interceptor/latest/dio_cache_interceptor/CacheOptions/hitCacheOnErrorCodes.html)

Please update your integration and used store packages according to
the [Getting Started section](https://pub.dev/packages/flutter_map_cache#getting-started).
More information can be found in
the [dio_cache_interceptor changelog](https://pub.dev/packages/dio_cache_interceptor/changelog#400).

## [1.5.2] 2025-02-05

- Support for flutter_map v6, v7 and v8

## [1.5.1] 2024-05-27

- Support for flutter_map v6 and v7

## [1.5.0] 2024-02-19

- fix: assertion error when the total amount of bytes is unknown (thanks to
  @Thelm76).
- add: optional `cachePolicy` parameter (thanks to @Thelm76).
- Update README

## [1.4.4] 2024-02-10

- Add web as supported platform
- Update docs
- Add tests

## [1.4.3] 2024-02-06

- Fix: `CachedTileProvider.dio` had its `BaseOptions`
  overridden ([#12](https://github.com/josxha/flutter_map_plugins/issues/12),
  thanks to
  @Thelm76)
- Add tests

## [1.4.2] 2024-02-01

- Migrate GitHub repository to a multi-package repo.
- Update README and package links.

## [1.4.1] 2024-01-24

- Fix description of Isar in the README file.

## [1.4.0] 2024-01-24

- Add `dio` as a parameter to `CachedTileProvider`. You're now able to provide
  and reuse your own Dio instance (thanks to @PatrickWulfe).
- Deprecate the `dioOptions` parameter. Prefer creating your own Dio instance
  and provide it to the `dio` parameter.
- Update the README file (for example add isar to the list of supported storage
  backends).

## [1.3.1]  2023-10-20

- Remove exception from the console when tile requests get cancelled
  (see https://github.com/josxha/flutter_map_plugins/issues/3).

## [1.3.0]  2023-10-09

- Support for flutter_map
  version [^6.0.0](https://pub.dev/packages/flutter_map/changelog#600---20231009)
- Support
  to [cancel map tiles](https://github.com/fleaflet/flutter_map/pull/1622) if
  tiles are still loading but no
  longer needed (
  like [flutter_map_cancellable_tile_provider](https://pub.dev/packages/flutter_map_cancellable_tile_provider))
- Update documentation

## [1.2.0] 2023-06-28

#### CachedTileProvider

- Add the `List<Interceptor>? interceptors` as a Parameter and remove
  the `verbose` parameter. The interceptors will
  get applied before the cache interceptor.
- The `store` parameter is now required.
- Add the option to override the `hitCacheOnErrorExcept` parameter. By default,
  a cached request will not get used if
  the server returns with status code 401 or 403.
- Remove the `dio` parameter but set dio as a public field variable so that it
  can get modified after creation.
- Add `BaseOptions? dioOptions` as a parameter.

#### Fixes

- Use cache when device has no internet connection and a SocketException gets
  thrown.

## [1.1.1] 2023-06-22

- Update documentation and example project
- Use the user agent header provided by the `TileLayer`

## [1.1.0] 2023-06-09

- Add `maxStale` and `keyBuilder` as optional parameters
  to `CachedTileProvider`:

## [1.0.0] 2023-06-09

- Initial version.







 
