flutter_map_cache

Creator: coderz1093

Last updated:

Add to Cart

Description:

flutter map cache

flutter_map_cache #
A slim yet powerful caching plugin for flutter_map tile layers.








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.

Features #
The package uses dio with the
dio_cache_interceptor package
and supports the storage backend that
you like.
Supported storage backends are:



Storage backend
Description




In-Memory
- For testing purposes- flutter_map has memory caching itself


File System
- Easy to setup, no additional storage backend package required- potentially slower than using a database


Drift
- SQLite database- good platform support


Hive
- key-value database- easy to integrate


ObjectBox
- NoSQL, ACID compliant- Fast library- More complex integration


Isar
- NoSQL- Fast library- More complex integration



Other storage backends will be supported as soon as the underlying package
dio_cache_interceptor supports
them.
Getting started #

Add the packages you want to use to your pubspec.yaml file. Only add the
packages for the backend you want to use.

dependencies:
flutter_map: ^6.0.0 # in case you don't have it yet
flutter_map_cache: ^1.3.0 # this package
path_provider: ^2.1.2 # in case the storage backend requires a path

# drift
dio_cache_interceptor_db_store: ^5.1.0
sqlite3_flutter_libs: ^0.5.15

# file system
dio_cache_interceptor_file_store: ^1.2.2

# hive
dio_cache_interceptor_hive_store: ^3.2.1

# objectbox
dio_cache_interceptor_objectbox_store: ^1.1.3
objectbox_flutter_libs: ^1.4.1

# isar
isar: ^3.1.0+1
isar_flutter_libs: ^3.1.0+1
copied to clipboard

⚠️ 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 #

Click here to expand / hide.

First get the cache directory of the app (i.e. with
the path_provider
package).

import 'package:path_provider/path_provider.dart';

Future<String> getPath() async {
final cacheDirectory = await getTemporaryDirectory();
return cacheDirectory.path;
}
copied to clipboard

Then use the directory path to initialize the HiveCacheStore. You can wrap
FlutterMap inside a FutureBuilder to use
the getPath() method.

@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',
),
),
),
],
);
}
copied to clipboard


In Memory (for testing) #

Click here to expand / hide.
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,
),
),
],
);
}
}
copied to clipboard


File System #

Click here to expand / hide.
import 'dart:io';

import 'package:dio_cache_interceptor/dio_cache_interceptor.dart';
import 'package:dio_cache_interceptor_file_store/dio_cache_interceptor_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());
},
);
}
}
copied to clipboard


More examples #
You can find additional example implementations for other storage backends in
the example app
on GitHub.
Common use cases & frequent questions #
How about web? #

Click here to expand / hide.
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



Does this package support cancellation of tile requests? #

Click here to expand / hide.
Yes. This package includes the tile cancellation out of the box.
There is no need
for flutter_map_cancellable_tile_provider
when using
this package.


Remove the api key from the url before it gets used for caching #

Click here to expand / hide.
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(),
);
},
),
copied to clipboard


Can I use this package for an offline map? #

Click here to expand / hide.
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.


What if I want to use sqflite? #

Click here to expand / hide.
Because 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 package.


Additional information #
Pull requests are welcome. If you want to add support for another storage
backend you can check out
dio_cache_interceptor.
If you need help you
can open an issue
or join
the flutter_map discord server.

License

For personal and professional use. You cannot resell or redistribute these repositories in their original state.

Customer Reviews

There are no reviews.