Kotlin中getCurrentLocation函数返回初始值问题求助
问题原因与解决方案
问题核心分析
你遇到的问题本质是异步操作的执行顺序问题:
fusedLocationProviderClient.lastLocation.addOnCompleteListener是异步任务,它的回调代码会在后台获取到位置信息后才执行。- 但你的
getCurrentLocation函数是同步执行的——在回调还没来得及更新DBLatitude和DBLongitude之前,函数就已经执行到return语句,返回了初始的0.0值。 - 而UI控件能正常显示,是因为回调执行时确实更新了
binding.tvLatitude和binding.tvLongitude,这时候函数的返回值已经无关紧要了。
解决方案1:使用Kotlin协程(推荐)
将函数改为挂起函数,利用Tasks.await()把异步任务转为同步等待,确保获取到位置后再返回值:
private suspend fun getCurrentLocation(): String { var DBLatitude: Double = 0.0 var DBLongitude: Double = 0.0 if (checkPermissions()) { if (isLocationEnabled()) { if (ActivityCompat.checkSelfPermission( this, Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission( this, Manifest.permission.ACCESS_COARSE_LOCATION ) != PackageManager.PERMISSION_GRANTED ) { checkPermissions() } try { // 等待异步任务完成,获取位置结果 val location = Tasks.await(fusedLocationProviderClient.lastLocation) if (location == null) { Toast.makeText(this, "Null obtido", Toast.LENGTH_SHORT).show() } else { binding.tvLatitude.text = "" + location.latitude binding.tvLongitude.text = "" + location.longitude DBLatitude = location.latitude DBLongitude = location.longitude } } catch (e: Exception) { e.printStackTrace() Toast.makeText(this, "获取位置失败", Toast.LENGTH_SHORT).show() } } else { Toast.makeText(this, "Ligue a localização", Toast.LENGTH_SHORT).show() val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS) startActivity(intent) } } else { requestPermission() } return "" + DBLatitude + " " + DBLongitude }
调用方式
需要在协程作用域中调用该函数,比如使用页面的生命周期协程:
lifecycleScope.launch { val locationStr = getCurrentLocation() // 此处拿到的locationStr就是正确的经纬度,可直接发送到数据库 }
解决方案2:使用回调接口
如果不想用协程,可以定义回调接口,在位置获取完成后再处理结果:
1. 定义回调接口
interface LocationCallback { fun onLocationReceived(locationStr: String) }
2. 修改获取位置的函数
private fun getCurrentLocation(callback: LocationCallback) { var DBLatitude: Double = 0.0 var DBLongitude: Double = 0.0 if (checkPermissions()) { if (isLocationEnabled()) { if (ActivityCompat.checkSelfPermission( this, Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission( this, Manifest.permission.ACCESS_COARSE_LOCATION ) != PackageManager.PERMISSION_GRANTED ) { checkPermissions() } fusedLocationProviderClient.lastLocation.addOnCompleteListener(this) { task -> val location = task.result if (location == null) { Toast.makeText(this, "Null obtido", Toast.LENGTH_SHORT).show() callback.onLocationReceived("$DBLatitude $DBLongitude") } else { binding.tvLatitude.text = "" + location.latitude binding.tvLongitude.text = "" + location.longitude DBLatitude = location.latitude DBLongitude = location.longitude // 获取到位置后调用回调返回结果 callback.onLocationReceived("$DBLatitude $DBLongitude") } } } else { Toast.makeText(this, "Ligue a localização", Toast.LENGTH_SHORT).show() val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS) startActivity(intent) callback.onLocationReceived("$DBLatitude $DBLongitude") } } else { requestPermission() callback.onLocationReceived("$DBLatitude $DBLongitude") } }
3. 调用方式
getCurrentLocation(object : LocationCallback { override fun onLocationReceived(locationStr: String) { // 此处拿到正确的经纬度字符串,执行发送到数据库的逻辑 } })
内容的提问来源于stack exchange,提问作者Bruno
相关产品推荐
相关产品推荐

