first commit
This commit is contained in:
638
app_car/amap_flutter_search.md
Normal file
638
app_car/amap_flutter_search.md
Normal file
@@ -0,0 +1,638 @@
|
||||
# AMap Flutter Search - 高德地图搜索插件
|
||||
|
||||
## 模块概述
|
||||
|
||||
`amap_flutter_search` 是 OneApp 中基于高德地图 SDK 的搜索服务插件,提供了全面的地理信息搜索功能,包括 POI 搜索、路线规划、地址解析等服务。该插件为车辆导航、位置查找、路径规划等功能提供了强大的搜索能力支持。
|
||||
|
||||
## 核心功能
|
||||
|
||||
### 1. POI 搜索
|
||||
- **关键词搜索**:基于关键词的兴趣点搜索
|
||||
- **周边搜索**:指定位置周边的 POI 搜索
|
||||
- **分类搜索**:按类别筛选的 POI 搜索
|
||||
- **详情查询**:获取 POI 的详细信息
|
||||
|
||||
### 2. 路线规划
|
||||
- **驾车路线**:多种驾车路径规划策略
|
||||
- **步行路线**:行人路径规划
|
||||
- **骑行路线**:骑行路径规划
|
||||
- **公交路线**:公共交通路径规划
|
||||
- **货车路线**:货车专用路径规划
|
||||
|
||||
### 3. 地址解析
|
||||
- **地理编码**:地址转换为坐标
|
||||
- **逆地理编码**:坐标转换为地址
|
||||
- **输入提示**:地址输入智能提示
|
||||
- **行政区查询**:行政区域信息查询
|
||||
|
||||
### 4. 距离计算
|
||||
- **直线距离**:两点间直线距离计算
|
||||
- **驾车距离**:实际驾车距离和时间
|
||||
- **步行距离**:步行距离和时间
|
||||
- **批量计算**:批量距离矩阵计算
|
||||
|
||||
## 技术架构
|
||||
|
||||
### 架构设计
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ 应用层 │
|
||||
│ (app_navigation, app_car) │
|
||||
├─────────────────────────────────────┤
|
||||
│ AMap Flutter Search │
|
||||
│ ┌──────────┬──────────┬──────────┐ │
|
||||
│ │ POI搜索 │ 路线规划 │ 地址解析 │ │
|
||||
│ ├──────────┼──────────┼──────────┤ │
|
||||
│ │ 距离计算 │ 缓存管理 │ 数据处理 │ │
|
||||
│ └──────────┴──────────┴──────────┘ │
|
||||
├─────────────────────────────────────┤
|
||||
│ 高德地图 Search SDK │
|
||||
│ ┌──────────┬──────────┬──────────┐ │
|
||||
│ │ Android │ iOS │ 搜索引擎 │ │
|
||||
│ └──────────┴──────────┴──────────┘ │
|
||||
├─────────────────────────────────────┤
|
||||
│ 网络服务层 │
|
||||
│ (REST API, WebService) │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 核心组件
|
||||
|
||||
#### 1. POI 搜索管理器 (PoiSearchManager)
|
||||
```dart
|
||||
class AMapPoiSearchManager {
|
||||
// 关键词搜索
|
||||
Future<PoiResult> searchByKeyword(PoiKeywordSearchOption option);
|
||||
|
||||
// 周边搜索
|
||||
Future<PoiResult> searchNearby(PoiNearbySearchOption option);
|
||||
|
||||
// ID 搜索
|
||||
Future<PoiItem> searchById(String poiId);
|
||||
|
||||
// 分类搜索
|
||||
Future<PoiResult> searchByCategory(PoiCategorySearchOption option);
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. 路线规划管理器 (RouteSearchManager)
|
||||
```dart
|
||||
class AMapRouteSearchManager {
|
||||
// 驾车路线规划
|
||||
Future<DriveRouteResult> calculateDriveRoute(DriveRouteQuery query);
|
||||
|
||||
// 步行路线规划
|
||||
Future<WalkRouteResult> calculateWalkRoute(WalkRouteQuery query);
|
||||
|
||||
// 骑行路线规划
|
||||
Future<RideRouteResult> calculateRideRoute(RideRouteQuery query);
|
||||
|
||||
// 公交路线规划
|
||||
Future<BusRouteResult> calculateBusRoute(BusRouteQuery query);
|
||||
|
||||
// 货车路线规划
|
||||
Future<TruckRouteResult> calculateTruckRoute(TruckRouteQuery query);
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. 地理编码管理器 (GeocodeManager)
|
||||
```dart
|
||||
class AMapGeocodeManager {
|
||||
// 地理编码
|
||||
Future<GeocodeResult> geocode(GeocodeQuery query);
|
||||
|
||||
// 逆地理编码
|
||||
Future<RegeocodeResult> reverseGeocode(RegeocodeQuery query);
|
||||
|
||||
// 输入提示
|
||||
Future<List<TipItem>> inputTips(InputTipsQuery query);
|
||||
|
||||
// 行政区查询
|
||||
Future<DistrictResult> searchDistrict(DistrictQuery query);
|
||||
}
|
||||
```
|
||||
|
||||
#### 4. 距离计算器 (DistanceCalculator)
|
||||
```dart
|
||||
class AMapDistanceCalculator {
|
||||
// 计算两点距离
|
||||
Future<DistanceResult> calculateDistance(DistanceQuery query);
|
||||
|
||||
// 批量距离计算
|
||||
Future<List<DistanceResult>> calculateDistances(List<DistanceQuery> queries);
|
||||
|
||||
// 路径距离计算
|
||||
Future<RouteDistanceResult> calculateRouteDistance(RouteDistanceQuery query);
|
||||
}
|
||||
```
|
||||
|
||||
## 数据模型
|
||||
|
||||
### POI 模型
|
||||
```dart
|
||||
class PoiItem {
|
||||
final String poiId; // POI ID
|
||||
final String title; // POI 名称
|
||||
final String snippet; // POI 描述
|
||||
final LatLng latLng; // POI 坐标
|
||||
final String distance; // 距离
|
||||
final String tel; // 电话
|
||||
final String postcode; // 邮编
|
||||
final String website; // 网站
|
||||
final String email; // 邮箱
|
||||
final String province; // 省份
|
||||
final String city; // 城市
|
||||
final String district; // 区县
|
||||
final String address; // 地址
|
||||
final String direction; // 方向
|
||||
final String businessArea; // 商圈
|
||||
final String typeCode; // 类型编码
|
||||
final String typeDes; // 类型描述
|
||||
final List<Photo> photos; // 照片列表
|
||||
final List<String> shopID; // 商铺ID
|
||||
final IndoorData indoorData; // 室内数据
|
||||
}
|
||||
|
||||
class PoiResult {
|
||||
final List<PoiItem> pois;
|
||||
final int pageCount;
|
||||
final int totalCount;
|
||||
final SearchBound searchBound;
|
||||
final PoiQuery query;
|
||||
}
|
||||
```
|
||||
|
||||
### 路线模型
|
||||
```dart
|
||||
class DriveRouteResult {
|
||||
final List<DrivePath> paths;
|
||||
final RouteQuery startPos;
|
||||
final RouteQuery targetPos;
|
||||
final List<RouteQuery> viaPoints;
|
||||
final int taxiCost;
|
||||
}
|
||||
|
||||
class DrivePath {
|
||||
final String strategy; // 策略
|
||||
final int distance; // 距离(米)
|
||||
final int duration; // 时长(秒)
|
||||
final String tolls; // 过路费
|
||||
final String tollDistance; // 收费距离
|
||||
final String totalTrafficLights; // 红绿灯数
|
||||
final List<DriveStep> steps; // 路径段
|
||||
final List<TMC> tmcs; // 路况信息
|
||||
}
|
||||
|
||||
class DriveStep {
|
||||
final String instruction; // 行驶指示
|
||||
final String orientation; // 方向
|
||||
final String road; // 道路名称
|
||||
final int distance; // 距离
|
||||
final int duration; // 时长
|
||||
final List<LatLng> polyline; // 路径坐标
|
||||
final String action; // 导航动作
|
||||
final String assistantAction; // 辅助动作
|
||||
}
|
||||
```
|
||||
|
||||
### 地址模型
|
||||
```dart
|
||||
class RegeocodeResult {
|
||||
final RegeocodeAddress regeocodeAddress;
|
||||
final List<PoiItem> pois;
|
||||
final List<Road> roads;
|
||||
final List<RoadInter> roadInters;
|
||||
final List<AoiItem> aois;
|
||||
}
|
||||
|
||||
class RegeocodeAddress {
|
||||
final String formattedAddress; // 格式化地址
|
||||
final String country; // 国家
|
||||
final String province; // 省份
|
||||
final String city; // 城市
|
||||
final String district; // 区县
|
||||
final String township; // 乡镇
|
||||
final String neighborhood; // 社区
|
||||
final String building; // 建筑
|
||||
final String adcode; // 区域编码
|
||||
final String citycode; // 城市编码
|
||||
final List<StreetNumber> streetNumbers; // 门牌信息
|
||||
}
|
||||
```
|
||||
|
||||
## API 接口
|
||||
|
||||
### POI 搜索接口
|
||||
```dart
|
||||
abstract class PoiSearchService {
|
||||
// 关键词搜索
|
||||
Future<ApiResponse<PoiResult>> searchByKeyword(PoiKeywordSearchRequest request);
|
||||
|
||||
// 周边搜索
|
||||
Future<ApiResponse<PoiResult>> searchNearby(PoiNearbySearchRequest request);
|
||||
|
||||
// 多边形搜索
|
||||
Future<ApiResponse<PoiResult>> searchInPolygon(PoiPolygonSearchRequest request);
|
||||
|
||||
// POI 详情
|
||||
Future<ApiResponse<PoiItem>> getPoiDetail(String poiId);
|
||||
}
|
||||
```
|
||||
|
||||
### 路线规划接口
|
||||
```dart
|
||||
abstract class RouteSearchService {
|
||||
// 驾车路线规划
|
||||
Future<ApiResponse<DriveRouteResult>> planDriveRoute(DriveRouteRequest request);
|
||||
|
||||
// 步行路线规划
|
||||
Future<ApiResponse<WalkRouteResult>> planWalkRoute(WalkRouteRequest request);
|
||||
|
||||
// 骑行路线规划
|
||||
Future<ApiResponse<RideRouteResult>> planRideRoute(RideRouteRequest request);
|
||||
|
||||
// 公交路线规划
|
||||
Future<ApiResponse<BusRouteResult>> planBusRoute(BusRouteRequest request);
|
||||
}
|
||||
```
|
||||
|
||||
### 地理编码接口
|
||||
```dart
|
||||
abstract class GeocodeService {
|
||||
// 地理编码
|
||||
Future<ApiResponse<GeocodeResult>> geocode(GeocodeRequest request);
|
||||
|
||||
// 逆地理编码
|
||||
Future<ApiResponse<RegeocodeResult>> reverseGeocode(RegeocodeRequest request);
|
||||
|
||||
// 输入提示
|
||||
Future<ApiResponse<List<TipItem>>> getInputTips(InputTipsRequest request);
|
||||
|
||||
// 行政区搜索
|
||||
Future<ApiResponse<DistrictResult>> searchDistrict(DistrictRequest request);
|
||||
}
|
||||
```
|
||||
|
||||
## 配置管理
|
||||
|
||||
### 搜索配置
|
||||
```dart
|
||||
class SearchConfig {
|
||||
final String apiKey; // API 密钥
|
||||
final int timeoutMs; // 超时时间
|
||||
final int maxRetries; // 最大重试次数
|
||||
final bool enableCache; // 是否启用缓存
|
||||
final int cacheExpireTime; // 缓存过期时间
|
||||
final String language; // 语言设置
|
||||
final String region; // 区域设置
|
||||
|
||||
static const SearchConfig defaultConfig = SearchConfig(
|
||||
apiKey: '',
|
||||
timeoutMs: 30000,
|
||||
maxRetries: 3,
|
||||
enableCache: true,
|
||||
cacheExpireTime: 3600,
|
||||
language: 'zh-CN',
|
||||
region: 'CN',
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### POI 搜索配置
|
||||
```dart
|
||||
class PoiSearchConfig {
|
||||
final int pageSize; // 每页结果数
|
||||
final int maxPage; // 最大页数
|
||||
final String city; // 搜索城市
|
||||
final String types; // 搜索类型
|
||||
final bool extensions; // 是否返回扩展信息
|
||||
final String sortrule; // 排序规则
|
||||
|
||||
static const PoiSearchConfig defaultConfig = PoiSearchConfig(
|
||||
pageSize: 20,
|
||||
maxPage: 100,
|
||||
city: '',
|
||||
types: '',
|
||||
extensions: false,
|
||||
sortrule: 'distance',
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 使用示例
|
||||
|
||||
### POI 搜索示例
|
||||
```dart
|
||||
// 关键词搜索
|
||||
final searchOption = PoiKeywordSearchOption(
|
||||
keyword: '加油站',
|
||||
city: '北京',
|
||||
pageSize: 20,
|
||||
pageNum: 1,
|
||||
extensions: true,
|
||||
);
|
||||
|
||||
final poiResult = await AMapPoiSearchManager.instance.searchByKeyword(searchOption);
|
||||
|
||||
for (final poi in poiResult.pois) {
|
||||
print('POI 名称: ${poi.title}');
|
||||
print('POI 地址: ${poi.address}');
|
||||
print('POI 距离: ${poi.distance}');
|
||||
print('POI 坐标: ${poi.latLng.latitude}, ${poi.latLng.longitude}');
|
||||
}
|
||||
```
|
||||
|
||||
### 周边搜索示例
|
||||
```dart
|
||||
// 周边搜索
|
||||
final nearbyOption = PoiNearbySearchOption(
|
||||
keyword: '餐厅',
|
||||
center: LatLng(39.9042, 116.4074), // 搜索中心点
|
||||
radius: 1000, // 搜索半径 1000 米
|
||||
pageSize: 10,
|
||||
pageNum: 1,
|
||||
);
|
||||
|
||||
final nearbyResult = await AMapPoiSearchManager.instance.searchNearby(nearbyOption);
|
||||
|
||||
print('附近餐厅数量: ${nearbyResult.pois.length}');
|
||||
for (final restaurant in nearbyResult.pois) {
|
||||
print('餐厅: ${restaurant.title} - ${restaurant.distance}');
|
||||
}
|
||||
```
|
||||
|
||||
### 路线规划示例
|
||||
```dart
|
||||
// 驾车路线规划
|
||||
final driveQuery = DriveRouteQuery(
|
||||
fromPoint: RouteQuery(39.9042, 116.4074), // 起点
|
||||
toPoint: RouteQuery(39.9015, 116.3974), // 终点
|
||||
mode: DriveMode.fastest, // 最快路线
|
||||
avoidhighspeed: false, // 不避开高速
|
||||
avoidtolls: false, // 不避开收费
|
||||
avoidtrafficjam: true, // 避开拥堵
|
||||
);
|
||||
|
||||
final driveResult = await AMapRouteSearchManager.instance.calculateDriveRoute(driveQuery);
|
||||
|
||||
if (driveResult.paths.isNotEmpty) {
|
||||
final path = driveResult.paths.first;
|
||||
print('驾车距离: ${path.distance} 米');
|
||||
print('预计时间: ${path.duration} 秒');
|
||||
print('过路费: ${path.tolls} 元');
|
||||
|
||||
for (final step in path.steps) {
|
||||
print('导航指示: ${step.instruction}');
|
||||
print('道路: ${step.road}');
|
||||
print('距离: ${step.distance} 米');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 地理编码示例
|
||||
```dart
|
||||
// 地址转坐标
|
||||
final geocodeQuery = GeocodeQuery(
|
||||
locationName: '北京市朝阳区望京SOHO',
|
||||
city: '北京',
|
||||
);
|
||||
|
||||
final geocodeResult = await AMapGeocodeManager.instance.geocode(geocodeQuery);
|
||||
|
||||
if (geocodeResult.geocodeAddressList.isNotEmpty) {
|
||||
final address = geocodeResult.geocodeAddressList.first;
|
||||
print('地址坐标: ${address.latLonPoint.latitude}, ${address.latLonPoint.longitude}');
|
||||
}
|
||||
|
||||
// 坐标转地址
|
||||
final regeocodeQuery = RegeocodeQuery(
|
||||
latLonPoint: LatLng(39.9915, 116.4684),
|
||||
radius: 200.0,
|
||||
extensions: 'all',
|
||||
);
|
||||
|
||||
final regeocodeResult = await AMapGeocodeManager.instance.reverseGeocode(regeocodeQuery);
|
||||
print('格式化地址: ${regeocodeResult.regeocodeAddress.formattedAddress}');
|
||||
```
|
||||
|
||||
### 输入提示示例
|
||||
```dart
|
||||
// 地址输入提示
|
||||
final tipsQuery = InputTipsQuery(
|
||||
keyword: '王府井',
|
||||
city: '北京',
|
||||
datatype: 'all',
|
||||
);
|
||||
|
||||
final tipsList = await AMapGeocodeManager.instance.inputTips(tipsQuery);
|
||||
|
||||
for (final tip in tipsList) {
|
||||
print('提示: ${tip.name}');
|
||||
print('地址: ${tip.address}');
|
||||
if (tip.point != null) {
|
||||
print('坐标: ${tip.point!.latitude}, ${tip.point!.longitude}');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 测试策略
|
||||
|
||||
### 单元测试
|
||||
```dart
|
||||
group('AMapSearch Tests', () {
|
||||
test('should search POI by keyword', () async {
|
||||
// Given
|
||||
final searchOption = PoiKeywordSearchOption(
|
||||
keyword: '测试POI',
|
||||
city: '北京',
|
||||
);
|
||||
|
||||
// When
|
||||
final result = await AMapPoiSearchManager.instance.searchByKeyword(searchOption);
|
||||
|
||||
// Then
|
||||
expect(result.pois, isNotEmpty);
|
||||
expect(result.pois.first.title, contains('测试POI'));
|
||||
});
|
||||
|
||||
test('should calculate drive route', () async {
|
||||
// Given
|
||||
final query = DriveRouteQuery(
|
||||
fromPoint: RouteQuery(39.9042, 116.4074),
|
||||
toPoint: RouteQuery(39.9015, 116.3974),
|
||||
);
|
||||
|
||||
// When
|
||||
final result = await AMapRouteSearchManager.instance.calculateDriveRoute(query);
|
||||
|
||||
// Then
|
||||
expect(result.paths, isNotEmpty);
|
||||
expect(result.paths.first.distance, greaterThan(0));
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### 集成测试
|
||||
```dart
|
||||
group('Search Integration Tests', () {
|
||||
testWidgets('complete search flow', (tester) async {
|
||||
// 1. 搜索 POI
|
||||
final pois = await searchNearbyPois('加油站', currentLocation);
|
||||
|
||||
// 2. 选择目标 POI
|
||||
final targetPoi = pois.first;
|
||||
|
||||
// 3. 规划路线
|
||||
final route = await planRouteToDestination(currentLocation, targetPoi.latLng);
|
||||
|
||||
// 4. 验证结果
|
||||
expect(route.paths, isNotEmpty);
|
||||
expect(route.paths.first.steps, isNotEmpty);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## 性能优化
|
||||
|
||||
### 搜索优化
|
||||
- **搜索缓存**:缓存常用搜索结果
|
||||
- **预测搜索**:基于历史预测用户搜索
|
||||
- **分页加载**:大结果集分页加载
|
||||
- **搜索建议**:智能搜索建议减少请求
|
||||
|
||||
### 路线优化
|
||||
- **路线缓存**:缓存常用路线规划结果
|
||||
- **增量更新**:只更新路线变化部分
|
||||
- **压缩传输**:压缩路线数据减少传输量
|
||||
- **多线程处理**:并行处理多个路线请求
|
||||
|
||||
## 错误处理
|
||||
|
||||
### 搜索错误类型
|
||||
```dart
|
||||
enum SearchErrorType {
|
||||
networkError, // 网络错误
|
||||
apiKeyInvalid, // API Key 无效
|
||||
quotaExceeded, // 配额超限
|
||||
invalidParameter, // 参数无效
|
||||
noResult, // 无搜索结果
|
||||
serverError, // 服务器错误
|
||||
timeout // 请求超时
|
||||
}
|
||||
|
||||
class SearchException implements Exception {
|
||||
final SearchErrorType type;
|
||||
final String message;
|
||||
final int? errorCode;
|
||||
|
||||
const SearchException(this.type, this.message, [this.errorCode]);
|
||||
}
|
||||
```
|
||||
|
||||
### 错误处理示例
|
||||
```dart
|
||||
try {
|
||||
final result = await AMapPoiSearchManager.instance.searchByKeyword(searchOption);
|
||||
// 处理搜索结果
|
||||
} on SearchException catch (e) {
|
||||
switch (e.type) {
|
||||
case SearchErrorType.networkError:
|
||||
showErrorDialog('网络连接失败,请检查网络设置');
|
||||
break;
|
||||
case SearchErrorType.noResult:
|
||||
showInfoDialog('未找到相关结果,请尝试其他关键词');
|
||||
break;
|
||||
case SearchErrorType.quotaExceeded:
|
||||
showErrorDialog('搜索次数已达上限,请稍后再试');
|
||||
break;
|
||||
default:
|
||||
showErrorDialog('搜索失败: ${e.message}');
|
||||
}
|
||||
} catch (e) {
|
||||
showErrorDialog('未知错误: $e');
|
||||
}
|
||||
```
|
||||
|
||||
## 缓存策略
|
||||
|
||||
### 搜索结果缓存
|
||||
```dart
|
||||
class SearchCache {
|
||||
static const int maxCacheSize = 1000;
|
||||
static const Duration cacheExpiration = Duration(hours: 1);
|
||||
|
||||
// 缓存 POI 搜索结果
|
||||
static Future<void> cachePoiResult(String key, PoiResult result);
|
||||
|
||||
// 获取缓存的 POI 结果
|
||||
static Future<PoiResult?> getCachedPoiResult(String key);
|
||||
|
||||
// 缓存路线规划结果
|
||||
static Future<void> cacheRouteResult(String key, DriveRouteResult result);
|
||||
|
||||
// 获取缓存的路线结果
|
||||
static Future<DriveRouteResult?> getCachedRouteResult(String key);
|
||||
|
||||
// 清理过期缓存
|
||||
static Future<void> cleanExpiredCache();
|
||||
}
|
||||
```
|
||||
|
||||
## 配额管理
|
||||
|
||||
### API 配额监控
|
||||
```dart
|
||||
class QuotaManager {
|
||||
// 获取当前配额使用情况
|
||||
static Future<QuotaInfo> getCurrentQuota();
|
||||
|
||||
// 检查是否可以发起请求
|
||||
static Future<bool> canMakeRequest(RequestType type);
|
||||
|
||||
// 记录请求使用
|
||||
static Future<void> recordRequest(RequestType type);
|
||||
|
||||
// 获取配额重置时间
|
||||
static Future<DateTime> getQuotaResetTime();
|
||||
}
|
||||
|
||||
class QuotaInfo {
|
||||
final int dailyLimit; // 日限额
|
||||
final int dailyUsed; // 日使用量
|
||||
final int monthlyLimit; // 月限额
|
||||
final int monthlyUsed; // 月使用量
|
||||
final DateTime resetTime; // 重置时间
|
||||
}
|
||||
```
|
||||
|
||||
## 版本历史
|
||||
|
||||
### v3.1.22+1 (当前版本)
|
||||
- 支持最新的高德地图 API
|
||||
- 新增货车路线规划功能
|
||||
- 优化搜索性能和准确性
|
||||
- 修复路线规划稳定性问题
|
||||
|
||||
### v3.1.21
|
||||
- 支持室内 POI 搜索
|
||||
- 新增批量距离计算
|
||||
- 优化内存使用
|
||||
- 改进错误处理机制
|
||||
|
||||
## 依赖关系
|
||||
|
||||
### 内部依赖
|
||||
- `amap_flutter_base`: 高德地图基础库
|
||||
- `basic_network`: 网络请求服务
|
||||
- `basic_storage`: 本地存储服务
|
||||
|
||||
### 外部依赖
|
||||
- `dio`: HTTP 客户端
|
||||
- `cached_network_image`: 图片缓存
|
||||
- `sqflite`: 本地数据库
|
||||
|
||||
## 总结
|
||||
|
||||
`amap_flutter_search` 作为高德地图搜索服务的 Flutter 插件,为 OneApp 提供了全面的地理信息搜索能力。通过集成 POI 搜索、路线规划、地理编码、距离计算等功能,该插件能够满足车辆导航、位置服务、路径规划等多种业务需求。
|
||||
|
||||
插件在设计上充分考虑了性能优化、缓存管理、错误处理、配额控制等关键因素,确保在提供高质量搜索服务的同时,保持良好的用户体验和系统稳定性。这为 OneApp 的车联网和导航服务提供了强大的技术支撑。
|
||||
Reference in New Issue
Block a user