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

Kotlin开发中fetchLocation()本地变量无法传递到callAPI()如何解决

问题根源

fusedLocationProviderClient.lastLocation 是异步操作,你在 onViewCreated 里顺序调用 fetchLocation() 和 callAPI() 时,位置请求的成功回调还没执行,全局变量q还保持初始空值,所以调用接口会报错。


解决方案:在位置获取成功回调中触发接口请求

直接把callAPI()的调用移到addOnSuccessListener回调里,保证只有拿到经纬度之后再调用接口,同时优化原有代码的稳定性问题:

class BlankFragment : Fragment() {
    lateinit var fusedLocationProviderClient: FusedLocationProviderClient
    private val key = "5a812faf9e1e4a66b17223056210911"
    private val days = 1

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(requireActivity())
        fetchLocation()
        // 移除此处的callAPI()调用
    }

    private fun fetchLocation() {
        // 用ContextCompat检查权限,requireContext避免空指针
        if (ContextCompat.checkSelfPermission(requireContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) 
            != PackageManager.PERMISSION_GRANTED 
            && ContextCompat.checkSelfPermission(requireContext(), android.Manifest.permission.ACCESS_COARSE_LOCATION) 
            != PackageManager.PERMISSION_GRANTED
        ) {
            // 用Fragment原生申请权限方法,回调会走当前Fragment的onRequestPermissionsResult
            requestPermissions(arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), 101)
            return
        }
        val task = fusedLocationProviderClient.lastLocation
        task.addOnSuccessListener { location ->
            location?.let {
                val q = "${it.latitude},${it.longitude}"
                // 拿到经纬度后再调用接口
                callAPI(q)
            } ?: run {
                // 位置获取为空处理,比如提示用户开启定位、默认填城市名
                Toast.makeText(requireContext(), "无法获取当前位置,请检查定位开关", Toast.LENGTH_SHORT).show()
            }
        }
    }

    // 把q作为入参传入,避免全局变量脏数据问题
    private fun callAPI(q: String){  
        apiServices.getUserDetails(key, q, days).enqueue(
            // 原有接口回调逻辑
        )
    }

    // 重写权限申请结果回调,用户同意权限后重新获取位置
    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == 101) {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                fetchLocation()
            } else {
                Toast.makeText(requireContext(), "需要定位权限才能获取对应位置数据", Toast.LENGTH_SHORT).show()
            }
        }
    }
}

额外优化说明

  • 不要直接强转context为Activity,优先用Fragment提供的requireContext()、requireActivity()方法,避免空指针崩溃
  • 位置获取可能返回null,需要加异常分支处理,比如 fallback 到默认城市、提示用户打开定位等
  • 不要滥用全局变量存异步结果,优先把需要的值作为函数参数传递,避免时序不同步导致的脏数据问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 01:45:01