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

Kotlin中如何每秒刷新Google地图最新位置?求正确实现方案

问题

我是Kotlin新手,想在Google地图上实现跟随用户移动的标记,需要每秒更新位置。用FusedLocationProviderClient的lastLocation只能获取一次最新位置,尝试过用CountDownTimer每5秒手动请求,但知道这不是规范做法。想问下使用LocationCallback是不是正确的实现方式?

现有两段代码:

第一段:单次获取位置的实现

private fun setUpMap() {

        if (ActivityCompat.checkSelfPermission(
                getActivity()!!,
                Manifest.permission.ACCESS_FINE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
                getActivity()!!,
                Manifest.permission.ACCESS_COARSE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            return
        }
        map?.isMyLocationEnabled = true
        fusedLocationClient.lastLocation.addOnSuccessListener(getActivity()!!) { location ->
            if (location != null) {
                lastLocation = location
                val currentLatLong = LatLng(location.latitude, location.longitude)
                map?.isMyLocationEnabled = true
                
                //placing the current location to the map marker
                placeMarkerOnMap(currentLatLong)
                map?.animateCamera(CameraUpdateFactory.newLatLngZoom(currentLatLong, 16f))
            } else {
            
            }
        }
    }

第二段:用定时器循环请求位置的实现

private fun setUpMap() {
        val timer = object : CountDownTimer(Long.MAX_VALUE, 5000) {
            override fun onTick(millisUntilFinished: Long) {
        if (ActivityCompat.checkSelfPermission(
                getActivity()!!,
                Manifest.permission.ACCESS_FINE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
                getActivity()!!,
                Manifest.permission.ACCESS_COARSE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            return
        }
                map?.isMyLocationEnabled = true
                fusedLocationClient.lastLocation.addOnSuccessListener(getActivity()!!) { location ->
                    if (location != null) {
                        lastLocation = location
                        val currentLatLong = LatLng(location.latitude, location.longitude)
                        map?.isMyLocationEnabled = true
                        
                        //map marker
                        placeMarkerOnMap(currentLatLong)
                        map?.animateCamera(CameraUpdateFactory.newLatLngZoom(currentLatLong, 16f))
                        
                    } else {

                    }
                }
            }

            override fun onFinish() {
            }
        }
        timer.start()
    }

请问用Google地图实现位置持续更新的正确方式是什么?LocationCallback是不是合适的方案?


正确实现方式:使用LocationCallback

LocationCallback是Google官方推荐的实现位置持续更新的标准方案,比定时器循环请求高效得多——系统会根据你的配置智能调度位置更新,既保证及时性,又能避免不必要的耗电。

具体实现步骤

  1. 定义LocationCallback:处理位置更新的回调逻辑,在回调中更新地图标记和相机位置
  2. 创建LocationRequest:配置更新频率、精度等核心参数
  3. 请求位置更新:权限校验通过后,调用FusedLocationProviderClient发起持续更新请求
  4. 生命周期管理:在页面暂停/销毁时停止位置更新,避免资源浪费

完整代码示例

// 类成员变量
private lateinit var locationCallback: LocationCallback
private lateinit var locationRequest: LocationRequest

private fun setUpLocationUpdates() {
    // 1. 初始化LocationCallback,处理位置更新
    locationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult) {
            super.onLocationResult(locationResult)
            locationResult.lastLocation?.let { location ->
                lastLocation = location
                val currentLatLong = LatLng(location.latitude, location.longitude)
                
                // 更新地图标记和相机视角
                placeMarkerOnMap(currentLatLong)
                map?.animateCamera(CameraUpdateFactory.newLatLngZoom(currentLatLong, 16f))
            }
        }
    }

    // 2. 创建LocationRequest,配置更新参数
    locationRequest = LocationRequest.create().apply {
        interval = 1000 // 每秒更新一次(单位:毫秒)
        fastestInterval = 500 // 最快更新间隔,防止系统频繁推送
        priority = LocationRequest.PRIORITY_HIGH_ACCURACY // 高精度定位模式
    }

    // 3. 校验权限并发起位置更新请求
    if (ActivityCompat.checkSelfPermission(
            requireContext(),
            Manifest.permission.ACCESS_FINE_LOCATION
        ) == PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(
            requireContext(),
            Manifest.permission.ACCESS_COARSE_LOCATION
        ) == PackageManager.PERMISSION_GRANTED
    ) {
        fusedLocationClient.requestLocationUpdates(
            locationRequest,
            locationCallback,
            Looper.getMainLooper() // 在主线程处理回调,保证UI更新安全
        )
        map?.isMyLocationEnabled = true
    }
}

// 4. 生命周期管理:页面暂停时停止位置更新
override fun onPause() {
    super.onPause()
    fusedLocationClient.removeLocationUpdates(locationCallback)
}

// 页面恢复时重启位置更新
override fun onResume() {
    super.onResume()
    if (::locationCallback.isInitialized && ::locationRequest.isInitialized) {
        if (ActivityCompat.checkSelfPermission(
                requireContext(),
                Manifest.permission.ACCESS_FINE_LOCATION
            ) == PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(
                requireContext(),
                Manifest.permission.ACCESS_COARSE_LOCATION
            ) == PackageManager.PERMISSION_GRANTED
        ) {
            fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper())
        }
    }
}

为什么不推荐定时器方案?

  • 耗电严重:定时器会周期性唤醒设备请求位置,即使用户未移动也会执行请求,大幅增加电量消耗
  • 更新不及时:固定间隔请求可能错过用户移动的关键节点,而LocationCallback是系统主动推送位置变化
  • 系统限制:Android系统对后台频繁请求位置的应用有严格限制,可能被降频甚至禁止

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 08:15:29