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

Android应用从最小化恢复后Google Maps的OnLocationChanged未触发问题

解决Fragment中Google Maps最小化后OnLocationCallback不触发的问题

嗨,这个问题我之前碰到过好几个开发者咨询,核心问题基本都和组件生命周期的回调绑定丢失有关。咱们一步步来排查和解决:

1. 最常见原因:位置更新回调在后台未注销,恢复时未重新注册

当应用最小化时,Fragment会触发onPause/onStop生命周期方法,如果你的LocationListener(或者FusedLocationProvider的LocationCallback)没有在此时注销,系统可能会回收这个回调的绑定;而当应用恢复时,又没有重新注册,自然就收不到位置更新了。

正确的做法是在onResume中注册位置更新,onPause中注销,既保证恢复时能重新绑定,也避免后台不必要的耗电:

private lateinit var fusedLocationClient: FusedLocationProviderClient
private lateinit var locationCallback: LocationCallback
private var googleMap: GoogleMap? = null

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    val view = inflater.inflate(R.layout.fragment_map, container, false)
    
    // 初始化FusedLocationClient和回调
    fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireContext())
    locationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult) {
            locationResult.lastLocation?.let { location ->
                Log.d("LocationUpdate", "Lat: ${location.latitude}, Lng: ${location.longitude}")
                // 更新地图标记位置
                googleMap?.let { map ->
                    val markerPosition = LatLng(location.latitude, location.longitude)
                    map.moveCamera(CameraUpdateFactory.newLatLngZoom(markerPosition, 15f))
                    // 如果标记已存在就更新位置,否则创建
                    map.addMarker(MarkerOptions().position(markerPosition))?.let { marker ->
                        marker.position = markerPosition
                    }
                }
            }
        }
    }
    
    // 初始化地图
    val mapFragment = childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
    mapFragment.getMapAsync { map ->
        googleMap = map
        map.isMyLocationEnabled = true
        // 绑定地图生命周期,避免状态丢失
        lifecycle.addObserver(map)
    }
    
    return view
}

override fun onResume() {
    super.onResume()
    // 检查权限后重新请求位置更新
    if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
        val locationRequest = LocationRequest.create().apply {
            interval = 10000 // 10秒更新一次
            fastestInterval = 5000 // 最快5秒更新
            priority = LocationRequest.PRIORITY_HIGH_ACCURACY
        }
        fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper())
    } else {
        // 如果权限未授予,重新请求
        requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 1001)
    }
}

override fun onPause() {
    super.onPause()
    // 暂停位置更新,释放资源
    fusedLocationClient.removeLocationUpdates(locationCallback)
}

2. 排查Fragment是否被系统重建

如果你的设备内存不足,应用最小化后Fragment可能会被系统销毁,恢复时会重新创建。这时候原来的LocationListener实例已经失效,需要在Fragment重建时重新初始化所有位置相关组件。

可以在onViewCreated或者onActivityCreated中做初始化,而不是只在onCreateView中做一次,确保重建时能重新绑定。

3. 确认地图组件的生命周期绑定

确保你的SupportMapFragment或者MapView和当前Fragment的生命周期正确关联。比如上面代码中给googleMap添加了lifecycle.addObserver(map),这能保证地图的状态和Fragment同步,避免恢复时地图组件异常。

最后总结

90%的概率是因为没有在onResume中重新注册位置回调,按照上面的代码调整后,应该就能解决最小化恢复后标记不移动的问题了。如果还是不行,可以检查Logcat中是否有位置权限或者系统限制的报错信息,比如有些厂商的后台限制会阻止位置更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:04:25