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官方推荐的实现位置持续更新的标准方案,比定时器循环请求高效得多——系统会根据你的配置智能调度位置更新,既保证及时性,又能避免不必要的耗电。
具体实现步骤
- 定义LocationCallback:处理位置更新的回调逻辑,在回调中更新地图标记和相机位置
- 创建LocationRequest:配置更新频率、精度等核心参数
- 请求位置更新:权限校验通过后,调用
FusedLocationProviderClient发起持续更新请求 - 生命周期管理:在页面暂停/销毁时停止位置更新,避免资源浪费
完整代码示例
// 类成员变量 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 -
相关产品推荐
相关产品推荐

