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

点击两次Google Map跳转按钮后应用崩溃:Kotlin空指针异常

解决KotlinNullPointerException在Google Map跳转按钮点击后的崩溃问题

看起来你遇到的问题很明确:第二次点击跳转按钮后,mMap变量为空,触发了KotlinNullPointerException,错误日志指向MyNavigationActivity.kt:261的moveCamera方法里的mMap!!.moveCamera调用。下面我来帮你分析原因并给出修复方案:

问题根源

mMap被定义为可空类型GoogleMap?,但你在代码中多处使用了非空断言!!——这种操作会在变量为空时直接抛出空指针异常。第二次点击按钮时,可能出现以下情况:

  • 地图视图的生命周期状态变化(比如从后台恢复后)导致mMap被置为null
  • getCurrentLocation的异步回调执行时,mMap还未完成初始化(虽然第一次点击没问题,但第二次操作可能触发了重复的权限请求或地图重新加载)
  • 没有妥善管理MapView的生命周期,导致地图实例被回收

修复步骤

1. 替换非空断言!!为安全调用?.

首先修改moveCamera方法,避免直接强制非空:

private fun moveCamera(latLng: LatLng, zoom: Float) {
    mMap?.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, zoom)) ?: run {
        // 给用户提示地图未准备好
        Toast.makeText(this, "地图加载中,请稍后重试", Toast.LENGTH_SHORT).show()
    }
}

2. 确保仅在地图初始化完成后执行操作

添加一个标记位跟踪地图是否准备就绪,避免在地图未加载完成时触发操作:

private var isMapReady = false

override fun onMapReady(googleMap: GoogleMap?) {
    mapView.onResume()
    mMap = googleMap
    isMapReady = true // 标记地图已初始化完成
    askPermissionLocation()
    // ... 你的其他代码
}

// 修改按钮点击事件
B_search.setOnClickListener {
    if (isMapReady) {
        searchArea()
    } else {
        Toast.makeText(this, "地图正在加载,请稍候", Toast.LENGTH_SHORT).show()
    }
}

3. 在异步回调中检查mMap状态

在getCurrentLocation的回调里,先确认mMap不为空再执行后续操作:

override fun onComplete(loc: Task<Location>) {
    if (loc.isSuccessful) {
        val currentLocation = loc.result as Location?
        if (currentLocation != null && mMap != null) {
            moveCamera(
                LatLng(currentLocation.latitude, currentLocation.longitude),
                DEFAULT_ZOOM
            )
            latitude = currentLocation.latitude
            longitude = currentLocation.longitude
        } else if (mMap == null) {
            Toast.makeText(this@MyNavigationActivity, "地图未准备好,请稍后再试", Toast.LENGTH_SHORT).show()
        }
    } else {
        askPermissionLocation()
    }
}

4. 完善MapView的生命周期管理

MapView需要和Activity的生命周期同步,否则可能导致地图实例被回收。添加以下生命周期方法:

override fun onResume() {
    super.onResume()
    mapView.onResume()
}

override fun onPause() {
    super.onPause()
    mapView.onPause()
}

override fun onDestroy() {
    super.onDestroy()
    mapView.onDestroy()
}

override fun onLowMemory() {
    super.onLowMemory()
    mapView.onLowMemory()
}

额外优化建议

  • 在searchArea方法中,也对mMap使用安全调用?.,比如mMap?.addMarker(markerOptions),避免同样的空指针问题
  • 考虑使用lateinit替代可空类型,但要确保mMap在使用前一定被初始化(不过MapView的异步初始化特性,用可空类型加安全调用更稳妥)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:34:38