Android高德地图开发从入门到精通实战路径详解

引言
随着移动互联网的快速发展,地图服务已成为各类App的标配功能。高德地图作为国内领先的地图服务提供商,提供了功能强大、性能稳定的地图SDK,广泛应用于出行、物流、社交、O2O等众多领域。本文将从零开始,系统性地讲解Android平台下高德地图的开发实战路径,涵盖从环境搭建、基础功能实现到高级特性应用的完整流程,并通过详尽的代码示例帮助开发者快速上手并精通高德地图开发。
一、环境准备与SDK集成
1.1 获取高德开发者账号与API Key
首先,需要在高德开放平台注册开发者账号并创建应用,获取API Key(也称为Key)。
步骤:
访问
高德开放平台
注册账号并登录
进入控制台,点击“创建新应用”
填写应用名称、类型等信息
在应用详情页,点击“添加Key”
选择“Android平台”,填写包名和SHA1指纹(可通过Android Studio的Gradle面板或命令行获取)
生成Key并妥善保存
获取SHA1指纹的方法:
# 使用keytool命令(Windows/Linux/Mac)
keytool -list -v -keystore your_keystore_path -alias your_alias -storepass your_password -keypass your_password

# 如果使用debug keystore(开发阶段)
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
1.2 集成高德地图SDK
在Android项目中集成高德地图SDK,推荐使用Gradle依赖方式。
步骤:
在项目级
build.gradle
中添加高德仓库:
allprojects {
repositories {
google()
jcenter()
maven { url ‘https://maven.google.com’ }
// 高德地图仓库
maven { url ‘https://repo.amap.com/content/repositories/releases/’ }
}
}
在模块级
build.gradle
中添加依赖:
dependencies {
// 基础地图SDK(必须)
implementation ‘com.amap.api:map2d:latest.release’
// 3D地图SDK(可选)
implementation ‘com.amap.api:3dmap:latest.release’
// 搜索SDK(可选)
implementation ‘com.amap.api:search:latest.release’
// 定位SDK(可选)
implementation ‘com.amap.api:location:latest.release’
// 导航SDK(可选)
implementation ‘com.amap.api:navi:latest.release’
}
在
AndroidManifest.xml
中添加必要的权限和配置:












1.3 创建地图视图
在布局文件中添加地图容器:




在Activity中初始化地图:
public class MainActivity extends AppCompatActivity {
private MapView mapView;
private AMap aMap;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

// 初始化地图
mapView = findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState); // 必须调用

if (aMap == null) {
aMap = mapView.getMap();
}

// 设置地图类型
aMap.setMapType(AMap.MAP_TYPE_NORMAL); // 普通地图
// aMap.setMapType(AMap.MAP_TYPE_SATELLITE); // 卫星地图
// aMap.setMapType(AMap.MAP_TYPE_NIGHT); // 夜间地图

// 设置缩放级别(3-20)
aMap.moveCamera(CameraUpdateFactory.zoomTo(15));
}

@Override
protected void onResume() {
super.onResume();
mapView.onResume();
}

@Override
protected void onPause() {
super.onPause();
mapView.onPause();
}

@Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
}
二、基础功能实现
2.1 地图基本操作
2.1.1 地图类型切换
// 切换到普通地图
aMap.setMapType(AMap.MAP_TYPE_NORMAL);

// 切换到卫星地图
aMap.setMapType(AMap.MAP_TYPE_SATELLITE);

// 切换到夜间地图
aMap.setMapType(AMap.MAP_TYPE_NIGHT);

// 切换到公交地图
aMap.setMapType(AMap.MAP_TYPE_BUS);
2.1.2 地图缩放与移动
// 设置缩放级别(3-20)
aMap.moveCamera(CameraUpdateFactory.zoomTo(15));

// 移动到指定位置
LatLng center = new LatLng(39.904556, 116.401394); // 北京天安门
aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(center, 15));

// 平滑移动
aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(center, 15), 1000, null);

// 获取当前地图状态
CameraPosition position = aMap.getCameraPosition();
Log.d(“Map”, “当前中心点:” + position.target);
Log.d(“Map”, “当前缩放级别:” + position.zoom);
Log.d(“Map”, “当前倾斜角度:” + position.tilt);
Log.d(“Map”, “当前旋转角度:” + position.bearing);
2.1.3 地图点击事件
// 设置地图点击监听器
aMap.setOnMapClickListener(new AMap.OnMapClickListener() {
@Override
public void onMapClick(LatLng latLng) {
// 点击地图任意位置
Log.d(“Map”, “点击位置:” + latLng.latitude + “, ” + latLng.longitude);

// 在点击位置添加标记
addMarker(latLng);
}
});

// 设置地图长按监听器
aMap.setOnMapLongClickListener(new AMap.OnMapLongClickListener() {
@Override
public void onMapLongClick(LatLng latLng) {
// 长按地图任意位置
Log.d(“Map”, “长按位置:” + latLng.latitude + “, ” + latLng.longitude);
}
});
2.2 标记(Marker)管理
2.2.1 添加普通标记
// 创建标记选项
MarkerOptions markerOptions = new MarkerOptions()
.position(new LatLng(39.904556, 116.401394)) // 位置
.title(“北京天安门”) // 标题
.snippet(“北京市东城区”) // 摘要
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)) // 图标
.draggable(false); // 是否可拖拽

// 添加标记到地图
Marker marker = aMap.addMarker(markerOptions);
2.2.2 自定义标记图标
// 从资源文件加载自定义图标
BitmapDescriptor customIcon = BitmapDescriptorFactory.fromResource(R.drawable.custom_marker);

MarkerOptions markerOptions = new MarkerOptions()
.position(new LatLng(39.904556, 116.401394))
.title(“自定义标记”)
.icon(customIcon)
.anchor(0.5f, 1.0f); // 设置锚点(0.5f, 1.0f表示底部中心)

Marker marker = aMap.addMarker(markerOptions);
2.2.3 标记点击事件
// 设置标记点击监听器
aMap.setOnMarkerClickListener(new AMap.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(Marker marker) {
// 标记被点击
Log.d(“Map”, “标记被点击:” + marker.getTitle());

// 显示信息窗口
marker.showInfoWindow();

// 返回true表示消费事件,false表示继续传递
return true;
}
});

// 设置信息窗口点击监听器
aMap.setOnInfoWindowClickListener(new AMap.OnInfoWindowClickListener() {
@Override
public boolean onInfoWindowClick(Marker marker) {
// 信息窗口被点击
Log.d(“Map”, “信息窗口被点击:” + marker.getTitle());
return true;
}
});
2.2.4 批量管理标记
// 创建标记集合
List markers = new ArrayList<>();

// 批量添加标记
for (int i = 0; i < 10; i++) { LatLng position = new LatLng(39.904556 + i * 0.01, 116.401394 + i * 0.01); MarkerOptions options = new MarkerOptions() .position(position) .title("标记" + i) .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE)); Marker marker = aMap.addMarker(options); markers.add(marker); } // 批量显示/隐藏标记 for (Marker marker : markers) { marker.setVisible(true); // 或 false 隐藏 } // 批量删除标记 for (Marker marker : markers) { marker.remove(); } markers.clear(); 2.3 信息窗口(InfoWindow) 2.3.1 自定义信息窗口 // 自定义信息窗口适配器 class CustomInfoWindowAdapter implements AMap.InfoWindowAdapter { @Override public View getInfoWindow(Marker marker) { // 返回自定义视图 View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.custom_info_window, null); TextView title = view.findViewById(R.id.tv_title); TextView snippet = view.findViewById(R.id.tv_snippet); title.setText(marker.getTitle()); snippet.setText(marker.getSnippet()); return view; } @Override public View getInfoContents(Marker marker) { // 如果返回null,则使用默认样式 return null; } } // 设置自定义信息窗口适配器 aMap.setInfoWindowAdapter(new CustomInfoWindowAdapter()); 自定义信息窗口布局(custom_info_window.xml):


2.3.2 信息窗口生命周期管理
// 监听信息窗口状态变化
aMap.setOnInfoWindowChangeListener(new AMap.OnInfoWindowChangeListener() {
@Override
public void onInfoWindowShow(Marker marker) {
// 信息窗口显示
Log.d(“Map”, “信息窗口显示:” + marker.getTitle());
}

@Override
public void onInfoWindowHide(Marker marker) {
// 信息窗口隐藏
Log.d(“Map”, “信息窗口隐藏:” + marker.getTitle());
}
});

// 手动控制信息窗口
Marker marker = aMap.addMarker(new MarkerOptions()
.position(new LatLng(39.904556, 116.401394))
.title(“测试标记”));

// 显示信息窗口
marker.showInfoWindow();

// 隐藏信息窗口
marker.hideInfoWindow();

// 判断信息窗口是否显示
boolean isShown = marker.isInfoWindowShown();
2.4 图层管理
2.4.1 添加热力图
// 创建热力图数据点
List weightedLatLngList = new ArrayList<>();

// 添加数据点(经纬度和权重)
for (int i = 0; i < 100; i++) { double lat = 39.904556 + (Math.random() - 0.5) * 0.1; double lng = 116.401394 + (Math.random() - 0.5) * 0.1; double weight = Math.random() * 10; // 权重值 weightedLatLngList.add(new HeatmapTileProvider.Builder.WeightedLatLng( new LatLng(lat, lng), weight)); } // 创建热力图提供者 HeatmapTileProvider heatmapTileProvider = new HeatmapTileProvider.Builder() .weightedData(weightedLatLngList) // 数据 .radius(50) // 半径(像素) .opacity(0.6) // 透明度 .gradient(HeatmapTileProvider.DEFAULT_GRADIENT) // 渐变颜色 .build(); // 添加热力图到地图 TileOverlay tileOverlay = aMap.addTileOverlay(new TileOverlayOptions() .tileProvider(heatmapTileProvider)); 2.4.2 添加瓦片图层 // 创建瓦片图层提供者 UrlTileProvider tileProvider = new UrlTileProvider(256, 256) { @Override public URL getTileUrl(int x, int y, int zoom) { // 构建瓦片URL String url = String.format( "https://tile.openstreetmap.org/%d/%d/%d.png", zoom, x, y); try { return new URL(url); } catch (MalformedURLException e) { e.printStackTrace(); return null; } } }; // 添加瓦片图层 TileOverlay tileOverlay = aMap.addTileOverlay(new TileOverlayOptions() .tileProvider(tileProvider) .zIndex(100)); // 图层层级 2.4.3 添加地面图层(GroundOverlay) // 创建地面图层 GroundOverlayOptions groundOverlayOptions = new GroundOverlayOptions() .positionFromBounds(new LatLngBounds( new LatLng(39.900, 116.400), // 西南角 new LatLng(39.910, 116.410))) // 东北角 .image(BitmapDescriptorFactory.fromResource(R.drawable.ground_overlay_image)) .transparency(0.5f) // 透明度 .zIndex(50); // 添加到地图 GroundOverlay groundOverlay = aMap.addGroundOverlay(groundOverlayOptions); 三、定位与导航功能 3.1 定位功能实现 3.1.1 集成定位SDK // 在build.gradle中添加定位SDK依赖 dependencies { implementation 'com.amap.api:location:latest.release' } 3.1.2 基础定位实现 public class LocationActivity extends AppCompatActivity { private AMapLocationClient locationClient; private AMapLocationClientOption locationOption; private Marker locationMarker; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_location); // 初始化定位客户端 locationClient = new AMapLocationClient(this); // 设置定位参数 locationOption = new AMapLocationClientOption(); locationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy); // 高精度模式 locationOption.setNeedAddress(true); // 需要返回地址信息 locationOption.setInterval(2000); // 定位间隔(毫秒) locationOption.setHttpTimeOut(30000); // 网络请求超时时间 locationOption.setMockEnable(false); // 是否允许模拟定位 // 设置定位监听器 locationClient.setLocationListener(new AMapLocationListener() { @Override public void onLocationChanged(AMapLocation aMapLocation) { if (aMapLocation != null) { if (aMapLocation.getErrorCode() == 0) { // 定位成功 double latitude = aMapLocation.getLatitude(); double longitude = aMapLocation.getLongitude(); String address = aMapLocation.getAddress(); Log.d("Location", "定位成功:" + latitude + ", " + longitude); Log.d("Location", "地址:" + address); // 在地图上显示定位点 showLocationOnMap(latitude, longitude); } else { // 定位失败 Log.e("Location", "定位失败,错误码:" + aMapLocation.getErrorCode() + ",错误信息:" + aMapLocation.getErrorInfo()); } } } }); // 开始定位 locationClient.startLocation(); } private void showLocationOnMap(double latitude, double longitude) { // 移除旧的定位标记 if (locationMarker != null) { locationMarker.remove(); } // 创建新的定位标记 MarkerOptions options = new MarkerOptions() .position(new LatLng(latitude, longitude)) .title("当前位置") .icon(BitmapDescriptorFactory.fromResource(R.drawable.location_marker)) .anchor(0.5f, 0.5f); locationMarker = aMap.addMarker(options); // 移动地图到定位位置 aMap.moveCamera(CameraUpdateFactory.newLatLngZoom( new LatLng(latitude, longitude), 15)); } @Override protected void onDestroy() { super.onDestroy(); // 停止定位 if (locationClient != null) { locationClient.stopLocation(); locationClient.onDestroy(); } } } 3.1.3 高级定位功能 // 设置定位参数 AMapLocationClientOption option = new AMapLocationClientOption(); // 定位模式 option.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy); // 高精度 // option.setLocationMode(AMapLocationClientOption.AMapLocationMode.Battery_Saving); // 省电模式 // option.setLocationMode(AMapLocationClientOption.AMapLocationMode.Device_Sensors); // 仅设备模式 // 定位精度 option.setGpsFirst(true); // 优先使用GPS option.setHttpTimeOut(30000); // 网络请求超时时间 option.setInterval(2000); // 定位间隔 option.setNeedAddress(true); // 需要地址信息 option.setMockEnable(false); // 禁止模拟定位 // 设置定位参数 locationClient.setLocationOption(option); // 获取定位结果 AMapLocation location = locationClient.getLastKnownLocation(); if (location != null) { Log.d("Location", "最后已知位置:" + location.getLatitude() + ", " + location.getLongitude()); } 3.2 路径规划 3.2.1 集成搜索SDK // 在build.gradle中添加搜索SDK依赖 dependencies { implementation 'com.amap.api:search:latest.release' } 3.2.2 驾车路径规划 public class RoutePlanningActivity extends AppCompatActivity { private AMap aMap; private RouteSearch routeSearch; private List routeMarkers = new ArrayList<>();
private Polyline routePolyline;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_route_planning);

// 初始化地图
MapView mapView = findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
aMap = mapView.getMap();

// 初始化路径规划搜索
routeSearch = new RouteSearch(this);
routeSearch.setRouteSearchListener(new RouteSearch.OnRouteSearchListener() {
@Override
public void onBusRouteSearched(BusRouteResult busRouteResult, int i) {
// 公交路线搜索结果
}

@Override
public void onDriveRouteSearched(DriveRouteResult driveRouteResult, int i) {
// 驾车路线搜索结果
if (driveRouteResult != null && driveRouteResult.getPaths() != null) {
if (driveRouteResult.getPaths().size() > 0) {
DrivePath drivePath = driveRouteResult.getPaths().get(0);
drawRouteOnMap(drivePath);
}
}
}

@Override
public void onWalkRouteSearched(WalkRouteResult walkRouteResult, int i) {
// 步行路线搜索结果
}

@Override
public void onRideRouteSearched(RideRouteResult rideRouteResult, int i) {
// 骑行路线搜索结果
}
});

// 设置路径规划按钮点击事件
findViewById(R.id.btn_plan_route).setOnClickListener(v -> {
planRoute();
});
}

private void planRoute() {
// 设置起点和终点
LatLonPoint startPoint = new LatLonPoint(39.904556, 116.401394); // 北京天安门
LatLonPoint endPoint = new LatLonPoint(39.914556, 116.411394); // 北京故宫

// 创建驾车路径规划请求
RouteSearch.FromAndTo fromAndTo = new RouteSearch.FromAndTo(startPoint, endPoint);

// 设置路径规划模式
RouteSearch.DriveRouteQuery query = new RouteSearch.DriveRouteQuery(
fromAndTo,
RouteSearch.DRIVING_DEFAULT, // 驾车模式
null, // 途经点
null, // 避让区域
“” // 避让道路
);

// 发起路径规划请求
routeSearch.calculateDriveRouteAsyn(query);
}

private void drawRouteOnMap(DrivePath drivePath) {
// 清除之前的路线
clearRoute();

// 获取路线坐标点
List points = drivePath.getSteps().get(0).getPolyline();

// 转换为LatLng列表
List latLngs = new ArrayList<>();
for (LatLonPoint point : points) {
latLngs.add(new LatLng(point.getLatitude(), point.getLongitude()));
}

// 绘制路线
routePolyline = aMap.addPolyline(new PolylineOptions()
.addAll(latLngs)
.color(Color.BLUE)
.width(10));

// 添加起点和终点标记
addStartEndMarkers(latLngs.get(0), latLngs.get(latLngs.size() – 1));

// 移动地图到路线范围
LatLngBounds.Builder builder = new LatLngBounds.Builder();
for (LatLng latLng : latLngs) {
builder.include(latLng);
}
aMap.moveCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 100));
}

private void addStartEndMarkers(LatLng start, LatLng end) {
// 起点标记
MarkerOptions startMarker = new MarkerOptions()
.position(start)
.title(“起点”)
.icon(BitmapDescriptorFactory.fromResource(R.drawable.marker_start));
routeMarkers.add(aMap.addMarker(startMarker));

// 终点标记
MarkerOptions endMarker = new MarkerOptions()
.position(end)
.title(“终点”)
.icon(BitmapDescriptorFactory.fromResource(R.drawable.marker_end));
routeMarkers.add(aMap.addMarker(endMarker));
}

private void clearRoute() {
// 清除路线
if (routePolyline != null) {
routePolyline.remove();
routePolyline = null;
}

// 清除标记
for (Marker marker : routeMarkers) {
marker.remove();
}
routeMarkers.clear();
}

@Override
protected void onDestroy() {
super.onDestroy();
if (routeSearch != null) {
routeSearch.destroy();
}
}
}
3.2.3 步行路径规划
// 步行路径规划
RouteSearch.WalkRouteQuery walkQuery = new RouteSearch.WalkRouteQuery(
new RouteSearch.FromAndTo(startPoint, endPoint),
RouteSearch.WALKING_DEFAULT
);

routeSearch.calculateWalkRouteAsyn(walkQuery);
3.2.4 公交路径规划
// 公交路径规划
RouteSearch.BusRouteQuery busQuery = new RouteSearch.BusRouteQuery(
new RouteSearch.FromAndTo(startPoint, endPoint),
RouteSearch.BUS_DEFAULT, // 公交模式
null, // 城市
0 // 第几页
);

routeSearch.calculateBusRouteAsyn(busQuery);
3.3 导航功能
3.3.1 集成导航SDK
// 在build.gradle中添加导航SDK依赖
dependencies {
implementation ‘com.amap.api:navi:latest.release’
}
3.3.2 启动导航
public class NavigationActivity extends AppCompatActivity {
private AMapNavi aMapNavi;
private NaviView naviView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_navigation);

// 初始化导航视图
naviView = findViewById(R.id.navi_view);

// 初始化导航引擎
aMapNavi = AMapNavi.getInstance(this);
aMapNavi.addAMapNaviListener(new AMapNaviListener() {
@Override
public void onInitNaviSuccess() {
// 导航初始化成功
Log.d(“Navigation”, “导航初始化成功”);

// 设置导航路线
setNaviRoute();
}

@Override
public void onInitNaviFailure() {
// 导航初始化失败
Log.e(“Navigation”, “导航初始化失败”);
}

// 其他导航监听器方法…
});

// 设置导航视图
aMapNavi.setNaviView(naviView);
}

private void setNaviRoute() {
// 设置起点和终点
NaviPoint startPoint = new NaviPoint(39.904556, 116.401394, “北京天安门”);
NaviPoint endPoint = new NaviPoint(39.914556, 116.411394, “北京故宫”);

// 创建导航路径规划策略
NaviStrategy strategy = new NaviStrategy();
strategy.setStrategy(NaviStrategy.STRATEGY_FASTEST); // 最快路线

// 设置导航路径
aMapNavi.setNaviRoute(startPoint, endPoint, strategy);

// 开始导航
aMapNavi.startNavi(NaviConstant.NAVI_MODE_NORMAL);
}

@Override
protected void onDestroy() {
super.onDestroy();
if (aMapNavi != null) {
aMapNavi.stopNavi();
aMapNavi.destroy();
}
}
}
四、高级功能与优化
4.1 地图性能优化
4.1.1 地图渲染优化
// 设置地图渲染参数
AMapUiSettings uiSettings = aMap.getUiSettings();

// 禁用不必要的功能以提升性能
uiSettings.setZoomControlsEnabled(false); // 禁用缩放控件
uiSettings.setCompassEnabled(false); // 禁用指南针
uiSettings.setScaleControlsEnabled(false); // 禁用比例尺
uiSettings.setAllGesturesEnabled(false); // 禁用手势

// 设置地图渲染模式
aMap.setRenderMode(AMap.RENDER_MODE_NORMAL); // 正常模式
// aMap.setRenderMode(AMap.RENDER_MODE_GL); // OpenGL模式(性能更好)

// 设置地图缓存
AMapLocalTileStorage.setTileStorageSize(200 * 1024 * 1024); // 200MB缓存
4.1.2 内存优化
// 在Activity生命周期中正确管理地图资源
@Override
protected void onResume() {
super.onResume();
mapView.onResume();
}

@Override
protected void onPause() {
super.onPause();
mapView.onPause();
}

@Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();

// 清理地图相关资源
if (aMap != null) {
aMap.clear(); // 清除所有地图元素
aMap = null;
}

// 清理定位资源
if (locationClient != null) {
locationClient.stopLocation();
locationClient.onDestroy();
}
}
4.1.3 网络请求优化
// 使用异步请求避免阻塞主线程
new Thread(new Runnable() {
@Override
public void run() {
// 在子线程中执行耗时操作
// 例如:批量添加大量标记
runOnUiThread(new Runnable() {
@Override
public void run() {
// 在主线程中更新UI
}
});
}
}).start();

// 使用线程池管理异步任务
ExecutorService executor = Executors.newFixedThreadPool(4);
executor.execute(new Runnable() {
@Override
public void run() {
// 执行任务
}
});
4.2 自定义地图样式
4.2.1 使用自定义地图样式
// 从JSON文件加载自定义样式
String styleJson = loadStyleFromAssets(“custom_map_style.json”);
aMap.setCustomMapStyle(styleJson);

// 或者直接设置样式
String customStyle = “{\”version\”:\”1.0\”,\”elements\”:{\”water\”:{\”color\”:\”#000000\”}}}”;
aMap.setCustomMapStyle(customStyle);
自定义地图样式JSON示例:
{
“version”: “1.0”,
“elements”: {
“water”: {
“color”: “#001a33”
},
“land”: {
“color”: “#f5f5f5”
},
“road”: {
“color”: “#ffffff”,
“width”: 1
},
“building”: {
“color”: “#d0d0d0”
}
}
}
4.2.2 动态切换地图样式
// 预定义几种地图样式
private String[] mapStyles = {
“{\”version\”:\”1.0\”,\”elements\”:{\”water\”:{\”color\”:\”#001a33\”}}}”,
“{\”version\”:\”1.0\”,\”elements\”:{\”water\”:{\”color\”:\”#003366\”}}}”,
“{\”version\”:\”1.0\”,\”elements\”:{\”water\”:{\”color\”:\”#006699\”}}}”
};

private int currentStyleIndex = 0;

// 切换地图样式
public void switchMapStyle() {
currentStyleIndex = (currentStyleIndex + 1) % mapStyles.length;
aMap.setCustomMapStyle(mapStyles[currentStyleIndex]);
}
4.3 地图事件与交互
4.3.1 地图手势监听
// 设置手势监听器
aMap.setOnMapTouchListener(new AMap.OnMapTouchListener() {
@Override
public void onTouch(MotionEvent event) {
// 监听地图触摸事件
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.d(“Map”, “地图触摸开始”);
break;
case MotionEvent.ACTION_UP:
Log.d(“Map”, “地图触摸结束”);
break;
}
}
});

// 设置手势状态监听器
aMap.setOnMapGestureListener(new AMap.OnMapGestureListener() {
@Override
public void onDoubleTap(float x, float y) {
// 双击事件
Log.d(“Map”, “双击位置:” + x + “, ” + y);
}

@Override
public void onSingleTap(float x, float y) {
// 单击事件
Log.d(“Map”, “单击位置:” + x + “, ” + y);
}

@Override
public void onFling(float x, float y, float velocityX, float velocityY) {
// 滑动事件
Log.d(“Map”, “滑动速度:” + velocityX + “, ” + velocityY);
}
});
4.3.2 地图状态变化监听
// 设置地图状态变化监听器
aMap.setOnCameraChangeListener(new AMap.OnCameraChangeListener() {
@Override
public void onCameraChange(CameraPosition cameraPosition) {
// 地图状态变化中
Log.d(“Map”, “地图状态变化中:” + cameraPosition.target);
}

@Override
public void onCameraChangeFinish(CameraPosition cameraPosition) {
// 地图状态变化结束
Log.d(“Map”, “地图状态变化结束:” + cameraPosition.target);

// 根据当前视野加载数据
loadMarkersInCurrentView(cameraPosition);
}
});

// 根据当前视野加载数据
private void loadMarkersInCurrentView(CameraPosition cameraPosition) {
// 获取当前地图边界
LatLngBounds bounds = aMap.getProjection().getVisibleRegion().latLngBounds;

// 根据边界查询数据
// 例如:查询边界内的POI点
queryPOIInBounds(bounds);
}
4.4 多线程与异步处理
4.4.1 使用AsyncTask(已废弃,但了解原理)
// AsyncTask示例(Android 11+已废弃,仅作参考)
private class LoadMarkersTask extends AsyncTask> {

@Override
protected List doInBackground(Void… voids) {
// 在后台线程中准备数据
List optionsList = new ArrayList<>();

for (int i = 0; i < 100; i++) { double lat = 39.904556 + (Math.random() - 0.5) * 0.1; double lng = 116.401394 + (Math.random() - 0.5) * 0.1; MarkerOptions options = new MarkerOptions() .position(new LatLng(lat, lng)) .title("标记" + i); optionsList.add(options); } return optionsList; } @Override protected void onPostExecute(List optionsList) {
// 在主线程中更新UI
for (MarkerOptions options : optionsList) {
aMap.addMarker(options);
}
}
}
4.4.2 使用RxJava(推荐)
// 在build.gradle中添加RxJava依赖
dependencies {
implementation ‘io.reactivex.rxjava2:rxjava:2.2.21’
implementation ‘io.reactivex.rxjava2:rxandroid:2.1.1’
}
// 使用RxJava进行异步处理
public void loadMarkersAsync() {
Observable.create((ObservableEmitter> emitter) -> {
// 在后台线程中准备数据
List optionsList = new ArrayList<>();

for (int i = 0; i < 100; i++) { double lat = 39.904556 + (Math.random() - 0.5) * 0.1; double lng = 116.401394 + (Math.random() - 0.5) * 0.1; MarkerOptions options = new MarkerOptions() .position(new LatLng(lat, lng)) .title("标记" + i); optionsList.add(options); } emitter.onNext(optionsList); emitter.onComplete(); }) .subscribeOn(Schedulers.io()) // 在IO线程执行 .observeOn(AndroidSchedulers.mainThread()) // 在主线程观察 .subscribe(new Consumer>() {
@Override
public void accept(List optionsList) throws Exception {
// 在主线程中更新UI
for (MarkerOptions options : optionsList) {
aMap.addMarker(options);
}
}
}, new Consumer() {
@Override
public void accept(Throwable throwable) throws Exception {
// 处理错误
Log.e(“Map”, “加载标记失败:” + throwable.getMessage());
}
});
}
4.4.3 使用Kotlin协程(如果使用Kotlin)
// Kotlin协程示例
class MapActivity : AppCompatActivity() {
private lateinit var aMap: AMap

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_map)

// 初始化地图…

// 启动协程
lifecycleScope.launch {
try {
// 在后台线程中准备数据
val optionsList = withContext(Dispatchers.IO) {
val list = mutableListOf()
for (i in 0 until 100) {
val lat = 39.904556 + (Math.random() – 0.5) * 0.1
val lng = 116.401394 + (Math.random() – 0.5) * 0.1

val options = MarkerOptions()
.position(LatLng(lat, lng))
.title(“标记$i”)

list.add(options)
}
list
}

// 在主线程中更新UI
optionsList.forEach { options ->
aMap.addMarker(options)
}
} catch (e: Exception) {
// 处理错误
Log.e(“Map”, “加载标记失败:${e.message}”)
}
}
}
}
五、实战项目案例
5.1 案例一:共享单车位置查询系统
5.1.1 项目需求分析
实时显示附近共享单车位置
支持按距离排序
点击单车显示详细信息
支持导航到指定单车
5.1.2 核心代码实现
public class BikeShareActivity extends AppCompatActivity {
private AMap aMap;
private List bikeList = new ArrayList<>();
private List bikeMarkers = new ArrayList<>();
private Marker selectedBikeMarker;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bike_share);

// 初始化地图
MapView mapView = findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
aMap = mapView.getMap();

// 设置地图点击事件
aMap.setOnMapClickListener(latLng -> {
// 点击地图空白处,取消选择
if (selectedBikeMarker != null) {
selectedBikeMarker.hideInfoWindow();
selectedBikeMarker = null;
}
});

// 设置标记点击事件
aMap.setOnMarkerClickListener(marker -> {
// 找到对应的单车
Bike bike = findBikeByMarker(marker);
if (bike != null) {
// 显示单车信息
marker.showInfoWindow();
selectedBikeMarker = marker;

// 显示操作面板
showBikeOperationPanel(bike);
}
return true;
});

// 加载单车数据
loadBikeData();
}

private void loadBikeData() {
// 模拟从服务器获取单车数据
List bikes = new ArrayList<>();

// 生成10辆单车数据
for (int i = 0; i < 10; i++) { double lat = 39.904556 + (Math.random() - 0.5) * 0.05; double lng = 116.401394 + (Math.random() - 0.5) * 0.05; Bike bike = new Bike(); bike.setId("Bike_" + i); bike.setLatitude(lat); bike.setLongitude(lng); bike.setBattery((int)(Math.random() * 100)); // 电量 bike.setPrice(1.5); // 价格 bikes.add(bike); } bikeList = bikes; displayBikesOnMap(); } private void displayBikesOnMap() { // 清除旧标记 clearBikeMarkers(); // 添加新标记 for (Bike bike : bikeList) { // 根据电量选择图标颜色 int iconRes; if (bike.getBattery() > 50) {
iconRes = R.drawable.bike_green;
} else if (bike.getBattery() > 20) {
iconRes = R.drawable.bike_yellow;
} else {
iconRes = R.drawable.bike_red;
}

MarkerOptions options = new MarkerOptions()
.position(new LatLng(bike.getLatitude(), bike.getLongitude()))
.title(“单车ID:” + bike.getId())
.snippet(“电量:” + bike.getBattery() + “% | 价格:” + bike.getPrice() + “元/分钟”)
.icon(BitmapDescriptorFactory.fromResource(iconRes))
.anchor(0.5f, 1.0f);

Marker marker = aMap.addMarker(options);
bikeMarkers.add(marker);
}
}

private void showBikeOperationPanel(Bike bike) {
// 显示操作面板
View panel = findViewById(R.id.bike_operation_panel);
panel.setVisibility(View.VISIBLE);

TextView tvBikeInfo = findViewById(R.id.tv_bike_info);
tvBikeInfo.setText(“单车ID:” + bike.getId() + “\n” +
“电量:” + bike.getBattery() + “%\n” +
“价格:” + bike.getPrice() + “元/分钟”);

// 设置按钮点击事件
findViewById(R.id.btn_navigate).setOnClickListener(v -> {
// 导航到单车
navigateToBike(bike);
});

findViewById(R.id.btn_unlock).setOnClickListener(v -> {
// 解锁单车
unlockBike(bike);
});
}

private void navigateToBike(Bike bike) {
// 使用高德导航SDK导航到单车
// 这里简化处理,实际项目中需要集成导航SDK
Intent intent = new Intent(this, NavigationActivity.class);
intent.putExtra(“destination_lat”, bike.getLatitude());
intent.putExtra(“destination_lng”, bike.getLongitude());
startActivity(intent);
}

private void unlockBike(Bike bike) {
// 调用解锁接口
// 这里简化处理
Toast.makeText(this, “正在解锁单车:” + bike.getId(), Toast.LENGTH_SHORT).show();

// 模拟解锁成功
new Handler().postDelayed(() -> {
Toast.makeText(this, “单车解锁成功!”, Toast.LENGTH_SHORT).show();
}, 2000);
}

private Bike findBikeByMarker(Marker marker) {
// 根据标记找到对应的单车
for (int i = 0; i < bikeMarkers.size(); i++) { if (bikeMarkers.get(i).equals(marker)) { return bikeList.get(i); } } return null; } private void clearBikeMarkers() { for (Marker marker : bikeMarkers) { marker.remove(); } bikeMarkers.clear(); } // 单车数据模型 static class Bike { private String id; private double latitude; private double longitude; private int battery; private double price; // getter和setter方法... } } 5.2 案例二:物流配送路径优化系统 5.2.1 项目需求分析 多点路径规划 实时交通路况显示 配送时间预估 路径优化算法 5.2.2 核心代码实现 public class LogisticsActivity extends AppCompatActivity { private AMap aMap; private RouteSearch routeSearch; private List deliveryPoints = new ArrayList<>();
private List pointMarkers = new ArrayList<>();
private List routePolylines = new ArrayList<>();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_logistics);

// 初始化地图
MapView mapView = findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
aMap = mapView.getMap();

// 初始化路径规划
routeSearch = new RouteSearch(this);
routeSearch.setRouteSearchListener(new RouteSearch.OnRouteSearchListener() {
@Override
public void onDriveRouteSearched(DriveRouteResult driveRouteResult, int i) {
if (driveRouteResult != null && driveRouteResult.getPaths() != null) {
if (driveRouteResult.getPaths().size() > 0) {
DrivePath drivePath = driveRouteResult.getPaths().get(0);
drawRouteOnMap(drivePath);
}
}
}

// 其他方法…
});

// 加载配送点数据
loadDeliveryPoints();

// 设置优化路径按钮
findViewById(R.id.btn_optimize_route).setOnClickListener(v -> {
optimizeRoute();
});
}

private void loadDeliveryPoints() {
// 模拟配送点数据
deliveryPoints.clear();

// 起点(仓库)
DeliveryPoint warehouse = new DeliveryPoint();
warehouse.setId(“WH001”);
warehouse.setName(“中央仓库”);
warehouse.setLatitude(39.904556);
warehouse.setLongitude(116.401394);
warehouse.setType(DeliveryPoint.TYPE_WAREHOUSE);
deliveryPoints.add(warehouse);

// 配送点
for (int i = 1; i <= 5; i++) { DeliveryPoint point = new DeliveryPoint(); point.setId("DP00" + i); point.setName("配送点" + i); point.setLatitude(39.904556 + (Math.random() - 0.5) * 0.05); point.setLongitude(116.401394 + (Math.random() - 0.5) * 0.05); point.setType(DeliveryPoint.TYPE_DELIVERY); deliveryPoints.add(point); } // 显示配送点 displayDeliveryPoints(); } private void displayDeliveryPoints() { // 清除旧标记 clearPointMarkers(); // 添加新标记 for (DeliveryPoint point : deliveryPoints) { int iconRes; if (point.getType() == DeliveryPoint.TYPE_WAREHOUSE) { iconRes = R.drawable.warehouse_marker; } else { iconRes = R.drawable.delivery_marker; } MarkerOptions options = new MarkerOptions() .position(new LatLng(point.getLatitude(), point.getLongitude())) .title(point.getName()) .snippet("ID:" + point.getId()) .icon(BitmapDescriptorFactory.fromResource(iconRes)) .anchor(0.5f, 1.0f); Marker marker = aMap.addMarker(options); pointMarkers.add(marker); } } private void optimizeRoute() { // 使用贪心算法优化路径(简化版) List optimizedPoints = optimizeDeliveryRoute(deliveryPoints);

// 规划路径
planRoute(optimizedPoints);
}

private List optimizeDeliveryRoute(List points) {
// 简化的路径优化算法(贪心算法)
List optimized = new ArrayList<>();

// 起点
DeliveryPoint warehouse = points.get(0);
optimized.add(warehouse);

// 剩余点
List remaining = new ArrayList<>(points.subList(1, points.size()));

// 从起点开始,每次选择最近的点
DeliveryPoint current = warehouse;
while (!remaining.isEmpty()) {
DeliveryPoint nearest = null;
double minDistance = Double.MAX_VALUE;

for (DeliveryPoint point : remaining) {
double distance = calculateDistance(current, point);
if (distance < minDistance) { minDistance = distance; nearest = point; } } if (nearest != null) { optimized.add(nearest); remaining.remove(nearest); current = nearest; } } return optimized; } private double calculateDistance(DeliveryPoint p1, DeliveryPoint p2) { // 计算两点间距离(简化版,实际应使用高德距离计算API) double lat1 = p1.getLatitude(); double lng1 = p1.getLongitude(); double lat2 = p2.getLatitude(); double lng2 = p2.getLongitude(); // 使用Haversine公式计算距离 double R = 6371; // 地球半径(公里) double dLat = Math.toRadians(lat2 - lat1); double dLng = Math.toRadians(lng2 - lng1); double a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * Math.sin(dLng/2) * Math.sin(dLng/2); double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); return R * c; } private void planRoute(List points) {
// 清除旧路线
clearRoutes();

// 规划相邻点之间的路径
for (int i = 0; i < points.size() - 1; i++) { DeliveryPoint from = points.get(i); DeliveryPoint to = points.get(i + 1); // 创建驾车路径规划请求 RouteSearch.FromAndTo fromAndTo = new RouteSearch.FromAndTo( new LatLonPoint(from.getLatitude(), from.getLongitude()), new LatLonPoint(to.getLatitude(), to.getLongitude()) ); RouteSearch.DriveRouteQuery query = new RouteSearch.DriveRouteQuery( fromAndTo, RouteSearch.DRIVING_DEFAULT, null, null, "" ); // 发起请求(实际项目中需要处理异步回调) routeSearch.calculateDriveRouteAsyn(query); } } private void drawRouteOnMap(DrivePath drivePath) { // 获取路线坐标点 List points = drivePath.getSteps().get(0).getPolyline();

// 转换为LatLng列表
List latLngs = new ArrayList<>();
for (LatLonPoint point : points) {
latLngs.add(new LatLng(point.getLatitude(), point.getLongitude()));
}

// 绘制路线
Polyline polyline = aMap.addPolyline(new PolylineOptions()
.addAll(latLngs)
.color(Color.parseColor(“#FF5722”))
.width(8));

routePolylines.add(polyline);
}

private void clearPointMarkers() {
for (Marker marker : pointMarkers) {
marker.remove();
}
pointMarkers.clear();
}

private void clearRoutes() {
for (Polyline polyline : routePolylines) {
polyline.remove();
}
routePolylines.clear();
}

// 配送点数据模型
static class DeliveryPoint {
public static final int TYPE_WAREHOUSE = 0;
public static final int TYPE_DELIVERY = 1;

private String id;
private String name;
private double latitude;
private double longitude;
private int type;

// getter和setter方法…
}
}
六、常见问题与解决方案
6.1 地图显示问题
6.1.1 地图不显示或显示异常
问题描述:
集成高德地图后,地图区域空白或显示异常。
解决方案:
检查API Key配置:
确保
AndroidManifest.xml
中配置了正确的API Key
检查包名和SHA1指纹是否与申请Key时一致
检查网络权限:


检查地图初始化代码:
// 确保在Activity生命周期中正确调用
mapView.onCreate(savedInstanceState);
mapView.onResume();
mapView.onPause();
mapView.onDestroy();
检查网络连接:
确保设备可以访问互联网
检查是否被防火墙或代理阻止
6.1.2 地图加载缓慢
解决方案:
优化地图渲染:
“`java
// 设置地图渲染模式
aMap.setRenderMode(AMap.RENDER_MODE_GL);
// 禁用不必要的功能
aMap.getUiSettings().setZoomControlsEnabled(false);
aMap.getUiSettings().setCompassEnabled(false);
2. **使用地图缓存:**
“`java
// 设置地图缓存大小
AMapLocalTileStorage.setTileStorageSize(200 * 1024 * 1024); // 200MB
减少地图元素数量:
避免一次性添加大量标记
使用分页加载或按需加载
6.2 定位问题
6.2.1 定位失败或精度低
解决方案:
检查权限:


检查定位参数:
AMapLocationClientOption option = new AMapLocationClientOption();
option.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
option.setGpsFirst(true); // 优先使用GPS
option.setInterval(2000); // 定位间隔
检查设备设置:
确保设备的GPS和定位服务已开启
检查是否在室内或信号弱的区域
6.2.2 定位权限被拒绝
解决方案:
动态申请权限(Android 6.0+):
// 检查权限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// 申请权限
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
1001);
} else {
// 权限已授予,开始定位
startLocation();
}
处理权限拒绝:
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 1001) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// 权限已授予
startLocation();
} else {
// 权限被拒绝
Toast.makeText(this, “需要定位权限才能使用此功能”, Toast.LENGTH_SHORT).show();
}
}
}
6.3 路径规划问题
6.3.1 路径规划失败
解决方案:
检查起点和终点:
确保起点和终点坐标有效
检查是否在高德地图覆盖范围内
检查网络连接:
确保设备可以访问互联网
检查网络是否稳定
检查请求参数:
// 确保请求参数正确
RouteSearch.DriveRouteQuery query = new RouteSearch.DriveRouteQuery(
fromAndTo,
RouteSearch.DRIVING_DEFAULT, // 正确的模式
null, null, “”
);
6.3.2 路径规划结果不准确
解决方案:
使用更精确的坐标:
使用高德地理编码API获取精确坐标
避免使用模糊地址
调整路径规划策略:
// 使用不同的路径规划模式
RouteSearch.DriveRouteQuery query = new RouteSearch.DriveRouteQuery(
fromAndTo,
RouteSearch.DRIVING_FASTEST, // 最快路线
// RouteSearch.DRIVING_SHORTEST, // 最短路线
// RouteSearch.DRIVING_AVOID_CONGESTION, // 避开拥堵
null, null, “”
);
考虑实时路况:
高德地图支持实时路况
在路径规划时考虑路况信息
七、性能优化与最佳实践
7.1 内存管理
7.1.1 避免内存泄漏
// 1. 在Activity销毁时清理资源
@Override
protected void onDestroy() {
super.onDestroy();

// 清理地图资源
if (mapView != null) {
mapView.onDestroy();
mapView = null;
}

// 清理定位资源
if (locationClient != null) {
locationClient.stopLocation();
locationClient.onDestroy();
locationClient = null;
}

// 清理导航资源
if (aMapNavi != null) {
aMapNavi.stopNavi();
aMapNavi.destroy();
aMapNavi = null;
}

// 清理其他资源
if (routeSearch != null) {
routeSearch.destroy();
routeSearch = null;
}
}

// 2. 使用弱引用避免内存泄漏
private static class WeakReferenceHandler extends Handler {
private final WeakReference activityRef;

public WeakReferenceHandler(Activity activity) {
activityRef = new WeakReference<>(activity);
}

@Override
public void handleMessage(Message msg) {
Activity activity = activityRef.get();
if (activity != null && !activity.isFinishing()) {
// 处理消息
}
}
}
7.1.2 优化标记管理
// 使用对象池管理标记
private static class MarkerPool {
private final Queue availableMarkers = new LinkedList<>();
private final List usedMarkers = new ArrayList<>();

public Marker obtain(AMap aMap, MarkerOptions options) {
Marker marker;
if (!availableMarkers.isEmpty()) {
marker = availableMarkers.poll();
// 重置标记属性
marker.setPosition(options.getPosition());
marker.setTitle(options.getTitle());
marker.setSnippet(options.getSnippet());
marker.setIcon(options.getIcon());
} else {
marker = aMap.addMarker(options);
}
usedMarkers.add(marker);
return marker;
}

public void recycle(Marker marker) {
if (usedMarkers.remove(marker)) {
marker.remove(); // 或者隐藏
availableMarkers.add(marker);
}
}

public void clear() {
for (Marker marker : usedMarkers) {
marker.remove();
}
usedMarkers.clear();
availableMarkers.clear();
}
}
7.2 网络优化
7.2.1 请求合并与缓存
// 使用缓存策略
public class MapDataCache {
private static final long CACHE_DURATION = 5 * 60 * 1000; // 5分钟

private Map cache = new HashMap<>();

static class CacheEntry {
Object data;
long timestamp;

CacheEntry(Object data) {
this.data = data;
this.timestamp = System.currentTimeMillis();
}

boolean isExpired() {
return System.currentTimeMillis() – timestamp > CACHE_DURATION;
}
}

public Object get(String key) {
CacheEntry entry = cache.get(key);
if (entry != null && !entry.isExpired()) {
return entry.data;
}
return null;
}

public void put(String key, Object data) {
cache.put(key, new CacheEntry(data));
}

public void clear() {
cache.clear();
}
}
7.2.2 使用HTTP/2和连接池
// 使用OkHttp进行网络请求(推荐)
dependencies {
implementation ‘com.squareup.okhttp3:okhttp:4.9.3’
}

// 创建OkHttpClient
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.connectionPool(new ConnectionPool(5, 5, TimeUnit.MINUTES))
.protocols(Collections.singletonList(Protocol.HTTP_2))
.build();

// 使用OkHttp进行请求
Request request = new Request.Builder()
.url(“https://api.amap.com/v3/…”)
.build();

okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
// 处理失败
}

@Override
public void onResponse(Call call, Response response) throws IOException {
// 处理响应
}
});
7.3 UI/UX优化
7.3.1 地图加载状态提示
// 显示加载进度
public class MapLoadingDialog extends Dialog {
private ProgressBar progressBar;
private TextView tvMessage;

public MapLoadingDialog(@NonNull Context context) {
super(context, R.style.MapLoadingDialog);
setContentView(R.layout.dialog_map_loading);

progressBar = findViewById(R.id.progress_bar);
tvMessage = findViewById(R.id.tv_message);
}

public void show(String message) {
tvMessage.setText(message);
show();
}

public void updateProgress(int progress) {
progressBar.setProgress(progress);
}

public void dismissWithSuccess() {
tvMessage.setText(“加载完成”);
new Handler().postDelayed(this::dismiss, 500);
}
}

// 在地图操作中使用
MapLoadingDialog loadingDialog = new MapLoadingDialog(this);
loadingDialog.show(“正在加载地图数据…”);

// 异步操作完成后
loadingDialog.updateProgress(100);
loadingDialog.dismissWithSuccess();
7.3.2 错误处理与重试机制
// 错误处理与重试
public class MapRequestManager {
private static final int MAX_RETRY_COUNT = 3;

public interface RequestCallback {
void onSuccess(T data);
void onError(String error);
}

public void requestWithRetry(String url, Class responseType,
RequestCallback callback) {
requestWithRetry(url, responseType, callback, 0);
}

private void requestWithRetry(String url, Class responseType,
RequestCallback callback, int retryCount) {
// 发起请求
// 这里简化处理,实际应使用网络请求库
new Thread(() -> {
try {
// 模拟网络请求
Thread.sleep(1000);

// 模拟成功
if (Math.random() > 0.3) {
// 解析响应
T response = parseResponse(responseType);

// 回调成功
new Handler(Looper.getMainLooper()).post(() -> {
callback.onSuccess(response);
});
} else {
throw new IOException(“网络请求失败”);
}
} catch (Exception e) {
if (retryCount < MAX_RETRY_COUNT) { // 重试 new Handler(Looper.getMainLooper()).postDelayed(() -> {
requestWithRetry(url, responseType, callback, retryCount + 1);
}, 1000 * (retryCount + 1)); // 指数退避
} else {
// 重试次数耗尽,回调错误
new Handler(Looper.getMainLooper()).post(() -> {
callback.onError(e.getMessage());
});
}
}
}).start();
}

private T parseResponse(Class responseType) {
// 解析响应
// 这里简化处理
return null;
}
}
八、总结
通过本文的详细讲解,我们系统地学习了Android平台下高德地图开发的完整路径:
8.1 学习路径回顾
环境准备与SDK集成
:获取API Key、集成SDK、配置权限
基础功能实现
:地图操作、标记管理、信息窗口、图层管理
定位与导航功能
:定位实现、路径规划、导航功能
高级功能与优化
:性能优化、自定义样式、事件处理、异步处理
实战项目案例
:共享单车系统、物流配送系统
常见问题与解决方案
:地图显示、定位、路径规划问题
性能优化与最佳实践
:内存管理、网络优化、UI/UX优化
8.2 进阶建议
深入学习高德地图SDK
:阅读官方文档,掌握更多高级功能
学习地图算法
:了解路径规划算法、地理编码算法等
关注性能优化
:持续优化地图应用的性能和用户体验
参与开源项目
:通过参与开源项目提升实战能力
关注行业动态
:关注地图技术发展趋势和新功能
8.3 资源推荐
官方文档
:
高德开放平台文档
示例代码
:高德地图官方示例项目
技术社区
:CSDN、掘金、GitHub上的相关项目
在线课程
:各大平台的高德地图开发课程
通过系统学习和实践,开发者可以快速掌握高德地图开发技能,并应用到实际项目中,创造出优秀的地图应用。记住,地图开发是一个持续学习和优化的过程,不断实践和总结是提升技能的关键。