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

Android项目中获取当前位置时Task未完成异常的解决方法

问题分析与解决方案

核心问题

你直接调用fusedLocationProviderClient.lastLocation.result时触发异常,是因为lastLocation返回的是异步Task,位置获取操作还没完成就去取结果,必然会抛出Task is not yet complete。Thread.sleep()完全不可靠——不同设备获取位置的耗时差异极大,短了可能还是失败,长了会阻塞主线程导致ANR。

正确解决方案

针对Kotlin项目,推荐两种规范的处理方式:


方式一:用回调处理异步逻辑

修改函数,通过回调返回生成的坐标,避免阻塞主线程:

fun generateRandomCoordinates(min: Int, max: Int, onResult: (LatLng?) -> Unit) {
    val meterCord = 0.00900900900901 / 1000
    val r = Random()
    // 修正随机范围:生成min到max之间的整数(包含两端)
    val randomMeters = r.nextInt(max - min + 1) + min
    val randomPM = r.nextInt(6)
    val metersCordN = meterCord * randomMeters.toDouble()

    fusedLocationProviderClient.lastLocation.addOnCompleteListener { task ->
        if (task.isSuccessful && task.result != null) {
            val currentLat = task.result.latitude
            val currentLong = task.result.longitude
            val coordinates = when (randomPM) {
                0 -> LatLng(currentLat + metersCordN, currentLong + metersCordN)
                1 -> LatLng(currentLat - metersCordN, currentLong - metersCordN)
                2 -> LatLng(currentLat + metersCordN, currentLong - metersCordN)
                3 -> LatLng(currentLat - metersCordN, currentLong + metersCordN)
                4 -> LatLng(currentLat, currentLong - metersCordN)
                else -> LatLng(currentLat - metersCordN, currentLong)
            }
            onResult(coordinates)
        } else {
            // 位置获取失败,返回null自行处理
            onResult(null)
        }
    }
}

调用示例:

generateRandomCoordinates(0, 10000) { latLng ->
    latLng?.let {
        // 在这里添加地图标记
    } ?: run {
        // 提示用户位置获取失败
    }
}

方式二:用Kotlin协程简化异步代码(推荐)

借助协程的await()方法,把异步逻辑写成同步风格的代码,避免回调嵌套:

  1. 先确保项目添加协程依赖(build.gradle):
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3"
implementation "com.google.android.gms:play-services-location:21.0.1"
  1. 修改为挂起函数:
import kotlinx.coroutines.tasks.await

suspend fun generateRandomCoordinates(min: Int, max: Int): LatLng? {
    val meterCord = 0.00900900900901 / 1000
    val r = Random()
    val randomMeters = r.nextInt(max - min + 1) + min
    val randomPM = r.nextInt(6)
    val metersCordN = meterCord * randomMeters.toDouble()

    return try {
        val location = fusedLocationProviderClient.lastLocation.await()
        location?.let {
            val currentLat = it.latitude
            val currentLong = it.longitude
            when (randomPM) {
                0 -> LatLng(currentLat + metersCordN, currentLong + metersCordN)
                1 -> LatLng(currentLat - metersCordN, currentLong - metersCordN)
                2 -> LatLng(currentLat + metersCordN, currentLong - metersCordN)
                3 -> LatLng(currentLat - metersCordN, currentLong + metersCordN)
                4 -> LatLng(currentLat, currentLong - metersCordN)
                else -> LatLng(currentLat - metersCordN, currentLong)
            }
        }
    } catch (e: Exception) {
        // 捕获获取位置时的异常(比如权限不足)
        null
    }
}

调用示例(在Activity/Fragment的协程作用域中):

lifecycleScope.launch {
    val randomLatLng = generateRandomCoordinates(0, 10000)
    randomLatLng?.let {
        // 添加地图标记
    } ?: run {
        // 处理位置获取失败
    }
}

额外修正点

原代码还有个小bug:randomMeters = r.nextInt(max + min)生成的范围是0到max+min-1,不符合你要的10公里(0-10000米)范围,已经在上面的代码里修正为r.nextInt(max - min + 1) + min。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 20:50:29