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

Android开发中addOnSuccessListener赋值后currentLocation仍为null如何解决

问题本质

你遇到的空值问题核心是定位请求是异步操作:

  • fusedLocationProviderClient.lastLocation 的 addOnSuccessListener 回调不会阻塞主线程执行,你在 onCreateView 中调用完 fetchLocation() 后立刻打印日志,此时定位请求还没有返回结果,currentLocation 自然还没被赋值,所以为空。
  • 你能看到TextView正常显示地址,是因为定位结果返回后才会执行回调里的赋值逻辑,两者存在时间差。

另外你现有代码里的权限申请逻辑也有问题:ActivityCompat.requestPermissions 同样是异步调用,申请后立刻判断请求码递归调用 fetchLocation() 是无效的,权限结果需要在 onRequestPermissionsResult 回调中接收。

修复方案

1. 调整定位后逻辑的执行时机

所有需要用到 currentLocation 的逻辑,统一放到定位成功的回调中执行,或者通过ViewModel的LiveData通知触发,不要在调用fetchLocation后立刻访问该变量。

2. 修复权限申请逻辑

移除fetchLocation里权限申请后的无效递归,重写权限申请结果回调,在用户授予权限后再触发定位。

3. 避免空指针崩溃

不要直接用 !! 强行解包可空变量,增加空判断避免异常。

修正后的示例代码

class EventNearMeFragment : Fragment() {
    private lateinit var binding: FragmentEventNearMeBinding
    private var fusedLocationProviderClient: FusedLocationProviderClient? = null
    private var currentLocation: Location? = null
    private val vm: EventNearMeViewModel by activityViewModels()
    // 定位权限请求码
    private val LOCATION_PERMISSION_CODE = 1000

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View {
        binding = FragmentEventNearMeBinding.inflate(inflater, container, false)
        fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(requireContext())
        fetchLocation()
        // 不要在这里直接访问currentLocation,此时还没赋值
        return binding.root
    }

    private fun fetchLocation() {
        if(ActivityCompat.checkSelfPermission(requireContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
            && ActivityCompat.checkSelfPermission(requireContext(),android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){
            // 申请权限,结果在回调中接收
            ActivityCompat.requestPermissions(requireActivity(), arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), LOCATION_PERMISSION_CODE)
            return
        }
        val task = fusedLocationProviderClient?.lastLocation
        task?.addOnSuccessListener { location -> 
            if(location != null) {
                this.currentLocation = location
                // 所有需要用到currentLocation的逻辑都放在这里执行,或者通知ViewModel处理
                Log.d("current location value", "${location.latitude} ${location.longitude}")
                val geoCoder = Geocoder(requireContext(), Locale.getDefault())
                val addresses = geoCoder.getFromLocation(location.latitude, location.longitude, 1)
                addresses?.firstOrNull()?.let { address ->
                    Toast.makeText(context, address.getAddressLine(0), Toast.LENGTH_SHORT).show()
                    binding.lblAddress.text = address.getAddressLine(0)
                    // 如果需要把位置传给ViewModel,在这里赋值
                    vm.updateCurrentLocation(location)
                }
            }
        }
    }

    // 重写权限申请结果回调
    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == LOCATION_PERMISSION_CODE) {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // 用户授予权限,重新触发定位
                fetchLocation()
            } else {
                // 用户拒绝权限,做降级处理
                Toast.makeText(context, "需要定位权限才能获取附近事件", Toast.LENGTH_SHORT).show()
            }
        }
    }
}

内容的提问来源于stack exchange,提问作者Chew Hong Yu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 22:30:01