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

WearOS开发:Flutter调用Kotlin获取当前位置如何等待异步任务?

问题原因

你的Kotlin函数始终返回2.2,核心原因是fusedLocationClient.getCurrentLocation()是异步操作——它在后台线程执行定位逻辑,addOnSuccessListener中的赋值代码要等定位完成才会触发,但你的函数在调用完getCurrentLocation()后立刻返回了初始值,此时回调还未执行,自然拿不到真实位置。

解决方案

要等待异步任务完成后再返回结果,有两种常用实现方式:

方式一:用Kotlin协程(推荐)

借助kotlinx-coroutines-play-services库的扩展函数,让异步Task可以用await()等待完成,实现类似Flutter中await的效果。

  1. 添加依赖
    在app模块的build.gradle中引入协程扩展库:
dependencies {
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.7.3"
}
  1. 改写定位方法为挂起函数
// 借助Activity的lifecycleScope管理协程生命周期
private suspend fun getLocationLongitude(): Double {
    var longitude = 2.2
    if (checkLocationPermission()) {
        val cancellationTokenSource = CancellationTokenSource()
        try {
            // 用await()等待定位任务完成
            val location = fusedLocationClient.getCurrentLocation(
                android.location.LocationRequest.QUALITY_HIGH_ACCURACY,
                cancellationTokenSource.token
            ).await()
            longitude = location.longitude
        } catch (e: Exception) {
            // 处理定位失败、取消等异常
            e.printStackTrace()
        }
    }
    return longitude
}

// 同理编写纬度获取方法
private suspend fun getLocationLatitude(): Double {
    var latitude = 2.2
    if (checkLocationPermission()) {
        val cancellationTokenSource = CancellationTokenSource()
        try {
            val location = fusedLocationClient.getCurrentLocation(
                android.location.LocationRequest.QUALITY_HIGH_ACCURACY,
                cancellationTokenSource.token
            ).await()
            latitude = location.latitude
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
    return latitude
}
  1. 在MethodChannel中用协程调用
// 初始化MethodChannel时设置处理器
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "myapp/location_permission").setMethodCallHandler { call, result ->
    when (call.method) {
        // ...其他方法(requestPermission、checkPermission)的处理
        "getLocationLongitude" -> {
            lifecycleScope.launch {
                val longitude = getLocationLongitude()
                result.success(longitude)
            }
        }
        "getLocationLatitude" -> {
            lifecycleScope.launch {
                val latitude = getLocationLatitude()
                result.success(latitude)
            }
        }
    }
}

方式二:直接用Task回调传递结果

不使用协程,直接在getCurrentLocation()的成功/失败回调中,通过MethodChannel的Result对象返回结果,无需单独编写返回值函数。

MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "myapp/location_permission").setMethodCallHandler { call, result ->
    when (call.method) {
        // ...其他方法处理
        "getLocationLongitude" -> {
            if (!checkLocationPermission()) {
                result.success(2.2)
                return@setMethodCallHandler
            }
            val cancellationTokenSource = CancellationTokenSource()
            fusedLocationClient.getCurrentLocation(
                android.location.LocationRequest.QUALITY_HIGH_ACCURACY,
                cancellationTokenSource.token
            ).addOnSuccessListener { location ->
                result.success(location.longitude)
            }.addOnFailureListener { e ->
                // 定位失败返回默认值,也可通过result.error()返回错误信息
                result.success(2.2)
                e.printStackTrace()
            }
        }
        "getLocationLatitude" -> {
            if (!checkLocationPermission()) {
                result.success(2.2)
                return@setMethodCallHandler
            }
            val cancellationTokenSource = CancellationTokenSource()
            fusedLocationClient.getCurrentLocation(
                android.location.LocationRequest.QUALITY_HIGH_ACCURACY,
                cancellationTokenSource.token
            ).addOnSuccessListener { location ->
                result.success(location.latitude)
            }.addOnFailureListener { e ->
                result.success(2.2)
                e.printStackTrace()
            }
        }
    }
}

注意事项

  • 两种方式都要处理无权限的情况,避免空指针或崩溃;
  • 可以根据需求调整LocationRequest的精度参数,比如用QUALITY_BALANCED_POWER_ACCURACY平衡功耗和精度;
  • 若定位超时,可以调用cancellationTokenSource.cancel()取消任务。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 18:53:16