You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin中Google Map位置更新时移动Marker而非重复添加的实现方法

解决Google Maps Android重复添加Marker的问题:复用单个Marker

这是个很常见的新手坑——每次位置更新就新建Marker确实会导致地图上堆一堆标记,咱们只需要在类里持有一个唯一的Marker实例,就能实现“只保留首个Marker并在位置更新时移动它”的需求。

步骤1:声明类级别的Marker变量

首先在你的Activity/Fragment里,定义一个可空的Marker变量,用来保存咱们要复用的那个标记:

private var userLocationMarker: Marker? = null

步骤2:在位置更新回调中处理Marker

假设你用的是FusedLocationProviderClient获取位置更新,或者在onLocationChanged回调里处理位置数据,拿到新的Location后先转换成LatLng,再判断Marker是否存在:

// 处理新位置的方法
private fun onNewLocationReceived(location: Location) {
    val newLatLng = LatLng(location.latitude, location.longitude)
    
    // 检查Marker是否已存在
    userLocationMarker?.let { existingMarker ->
        // 若已存在,直接更新它的位置
        existingMarker.position = newLatLng
    } ?: run {
        // 若不存在,创建新Marker并赋值给变量
        userLocationMarker = mMap.addMarker(
            MarkerOptions()
                .position(newLatLng)
                .title("我的位置")
                .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))
        )
    }

    // 可选:同时移动地图相机到新位置,提升用户体验
    mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(newLatLng, 15f))
}

关键注意点

  • 确保mMap对象已初始化完成(必须在onMapReady(googleMap: GoogleMap)回调里赋值),否则调用addMarker会触发空指针异常。
  • Marker的自定义样式(图标、标题等)只需要在首次创建时设置,后续更新位置不会改变这些属性。
  • 如果需要移除这个Marker,直接调用userLocationMarker?.remove(),再把变量置为null即可。

完整示例片段(结合MapReady回调)

class MapsActivity : AppCompatActivity(), OnMapReadyCallback {
    private lateinit var mMap: GoogleMap
    private var userLocationMarker: Marker? = null
    private lateinit var fusedLocationClient: FusedLocationProviderClient

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_maps)
        
        // 初始化地图Fragment
        val mapFragment = supportFragmentManager
            .findFragmentById(R.id.map) as SupportMapFragment
        mapFragment.getMapAsync(this)
        
        // 初始化位置服务客户端
        fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
    }

    override fun onMapReady(googleMap: GoogleMap) {
        mMap = googleMap
        // 开启我的位置图层(可选)
        mMap.isMyLocationEnabled = true
        
        // 启动位置更新监听
        startLocationUpdates()
    }

    private fun startLocationUpdates() {
        // 配置位置更新参数
        val locationRequest = LocationRequest.create().apply {
            interval = 10000 // 10秒更新一次
            fastestInterval = 5000 // 最快5秒更新一次
            priority = LocationRequest.PRIORITY_HIGH_ACCURACY
        }

        // 权限检查(记得在Manifest添加权限,并在运行时申请)
        if (ContextCompat.checkSelfPermission(
                this,
                Manifest.permission.ACCESS_FINE_LOCATION
            ) == PackageManager.PERMISSION_GRANTED
        ) {
            fusedLocationClient.requestLocationUpdates(
                locationRequest,
                locationCallback,
                Looper.getMainLooper()
            )
        }
    }

    // 位置更新回调
    private val locationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult) {
            super.onLocationResult(locationResult)
            locationResult.lastLocation?.let { location ->
                onNewLocationReceived(location)
            }
        }
    }

    private fun onNewLocationReceived(location: Location) {
        val newLatLng = LatLng(location.latitude, location.longitude)
        
        userLocationMarker?.let { existingMarker ->
            existingMarker.position = newLatLng
        } ?: run {
            userLocationMarker = mMap.addMarker(
                MarkerOptions()
                    .position(newLatLng)
                    .title("我的位置")
                    .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))
            )
        }

        mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(newLatLng, 15f))
    }

    // Activity销毁时移除位置更新监听
    override fun onDestroy() {
        super.onDestroy()
        fusedLocationClient.removeLocationUpdates(locationCallback)
    }
}

这样就能实现每次位置更新时,只移动已有的Marker,而不会重复创建新标记了。

内容的提问来源于stack exchange,提问作者hdiz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:59:51