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

骑手应用二次启动后Google Maps司机Marker不显示问题

问题分析与解决方案

核心问题

Constants是全局单例对象,其中的marketList和driversFound集合会在应用进程存活期间保留第一次启动时的数据:

  • 第二次启动时,marketList中存储的是旧GoogleMap实例创建的Marker,这些Marker无法在新的Map实例上显示
  • 旧的driversFound数据未清空,导致逻辑判断错误,不会重新添加新的Marker

修复步骤

1. 清空全局集合的时机

在HomeFragment的init方法开头,清空全局集合避免旧数据干扰:

private fun init() {
    // 清空全局集合,消除上次启动的残留数据
    Constants.marketList.clear()
    Constants.driversFound.clear()
    
    iFirebaseDriverLocationListener = this
    // ... 原有代码逻辑
}

2. 移除错误的IO协程

addDriverMarker中使用Dispatchers.IO是错误的,GoogleMap相关操作必须在主线程执行:

private fun addDriverMarker() {
    Log.d("MarkerDebug", "addDriverMarker is called ")

    if (Constants.driversFound.isNotEmpty()) {
        val newDriverKeys = Constants.driversFound.mapNotNull { it.key }
        val existingDriverKeys = Constants.marketList.keys

        // 移除不在当前列表中的司机Marker
        val removedDriverKeys = existingDriverKeys.subtract(newDriverKeys.toSet())
        for (key in removedDriverKeys) {
            Constants.marketList[key]?.remove()
            Constants.marketList.remove(key)
        }

        // 新增或更新司机Marker
        Constants.driversFound.forEach { driverGeoModel ->
            findDriverByKey(driverGeoModel)
            Log.d("MarkerDebug", "addDriverMarker is called when found driver: ${driverGeoModel.key}")
        }

        Snackbar.make(
            requireView(), getString(R.string.drivers_are_found), Snackbar.LENGTH_SHORT
        ).show()
    } else {
        // 清空所有Marker
        Constants.marketList.values.forEach { it.remove() }
        Constants.marketList.clear()
        Snackbar.make(
            requireView(), getString(R.string.drivers_are_not_found), Snackbar.LENGTH_SHORT
        ).show()
    }
}

3. 修复cityName变量作用域问题

loadAvailableDrivers中局部cityName覆盖成员变量,导致onDriverInfoLoadSuccess无法获取正确城市名:

// 在loadAvailableDrivers方法中,将局部变量赋值改为成员变量赋值
// val cityName = addressList!![0].locality
this.cityName = addressList!![0].locality

4. 重置firstTime标记

在onDestroyView中重置firstTime,避免多次启动后位置判断逻辑异常:

override fun onDestroyView() {
    super.onDestroyView()
    fusedLocationProviderClient.removeLocationUpdates(locationCallback)
    _binding = null
    firstTime = true // 重置首次位置标记
}

额外优化建议

  • 避免用全局单例存储UI相关对象(如Marker),建议将这些集合放在Fragment或ViewModel中管理
  • 所有GoogleMap操作必须在主线程执行,禁止在IO线程调用Map相关API
  • 在Fragment生命周期的销毁阶段清理资源,避免内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 20:04:51