Flutter地图缓存插件flutter_map_cache的使用
Flutter地图缓存插件flutter_map_cache的使用
简介
flutter_map_cache
是一个轻量级但功能强大的Flutter地图瓦片层缓存插件。它不仅有助于减少服务器负载,还能降低商业图块提供商的成本,并提升用户体验。
动机
- 许多图块提供者在其图块使用政策中要求用户缓存图块请求。
- 通过缓存图块可以减少图块请求的数量,从而降低成本。
- 缓存地图图块能为用户提供更好的体验,因为用户访问过的区域会立即加载。
- 缓存图块可以减少移动数据和带宽的使用。
功能
该包使用dio与dio_cache_interceptor支持多种存储后端:
存储后端 | 描述 |
---|---|
In-Memory | - 适用于测试 - flutter_map 本身有内存缓存 |
File System | - 易于设置,无需额外的存储后端包 - 可能比使用数据库慢 |
Drift | - SQLite数据库 - 良好的平台支持 |
Hive | - 键值数据库 - 易于集成 |
ObjectBox | - NoSQL, ACID兼容 - 快速库 - 集成更复杂 |
Isar | - NoSQL - 快速库 - 集成更复杂 |
入门指南
- 将需要使用的包添加到
pubspec.yaml
文件中:
dependencies:
flutter_map: ^6.0.0 # 如果你还没有这个包
flutter_map_cache: ^1.3.0 # 这个包
path_provider: ^2.1.2 # 如果存储后端需要路径
# 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
- ⚠️ 某些存储后端有自己的安装要求,请查阅相关包的文档。
使用方法
Hive 示例
import 'package:path_provider/path_provider.dart';
Future<String> getPath() async {
final cacheDirectory = await getTemporaryDirectory();
return cacheDirectory.path;
}
class MyMap extends StatelessWidget {
@override
Widget build(BuildContext context) {
return FutureBuilder<String>(
future: getPath(),
builder: (context, snapshot) {
if (snapshot.hasData) {
String path = snapshot.data!;
return FlutterMap(
options: MapOptions(),
children: [
TileLayer(
urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
tileProvider: CachedTileProvider(
maxStale: const Duration(days: 30),
store: HiveCacheStore(
path,
hiveBoxName: 'HiveCacheStore',
),
),
),
],
);
}
if (snapshot.hasError) {
return Center(child: Text(snapshot.error.toString()));
}
return const Center(child: CircularProgressIndicator());
},
);
}
}
内存缓存(用于测试)
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});
// 创建缓存存储作为字段变量
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(
store: _cacheStore,
),
),
],
);
}
}
文件系统缓存
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> {
final Future<CacheStore> _cacheStoreFuture = _getCacheStore();
static Future<CacheStore> _getCacheStore() async {
final dir = await getTemporaryDirectory();
return FileCacheStore('${dir.path}${Platform.pathSeparator}MapTiles');
}
@override
Widget build(BuildContext context) {
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(
store: cacheStore,
),
),
],
);
}
if (snapshot.hasError) {
return Center(child: Text(snapshot.error.toString()));
}
return const Center(child: CircularProgressIndicator());
},
);
}
}
常见问题
Web 支持
- In Memory:开箱即用
- Hive:使用IndexedDB支持Web
- Drift (SQLite):需要额外的Web设置步骤
图块请求取消支持
是的,此包包含图块取消功能。
如何在缓存前移除URL中的API密钥?
final _uuid = Uuid();
CachedTileProvider(
keyBuilder: (request) {
return _uuid.v5(
Uuid.NAMESPACE_URL,
request.uri.replace(queryParameters: {}).toString(),
);
},
),
是否可以用作离线地图?
此包不支持自动下载图块。只有之前在有网络连接时访问过的图块会在地图上显示。
是否支持sqflite?
由于dio_cache_interceptor
已经支持Drift作为SQLite解决方案,因此不太可能很快支持sqflite
。如果必须使用sqflite
,建议创建自己的图块提供程序。
更多信息
如果你需要更多帮助,可以在GitHub上提交问题或加入flutter_map Discord服务器。
更多关于Flutter地图缓存插件flutter_map_cache的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
1 回复