android - 如何让编译器等待OnCompleteListener Kotlin

标签 android multithreading kotlin

我正在使用此函数来获取用户位置,然后将该位置作为参数返回给另一个函数。但是,编译器不会等待OnComleteListener完成才返回null-因为位置变量已初始化为null。
谁能帮助我让编译器等待侦听器的定位结果?我可以从设备中获取位置信息,因为我可以在文本 View 中进行打印。
这是我指的功能:

@SuppressLint("MissingPermission", "SetTextI18n")
     fun getLastLocation(): Location? {

        var holder: Location? = null

        Log.e(TAG,"CALLED")
        if(CheckPermission()) {
            if(isLocationEnabled()) {
                fusedLocationProviderClient.lastLocation.addOnCompleteListener {task ->
                    var location = task.result
                    Log.e(TAG,"Location: $location")
                    if(location == null) {
                        getNewLocation()
                    } else {
                        holder = location
                        Log.e(TAG, "Holder1 = $holder")
                        locationText.text = "Your current coordinates are :\nLat: " + location.latitude + " ; Long: " + location.longitude
                    }
                }
                Log.e(TAG, "Holder2 = $holder")
            } else {
                Toast.makeText(this, "Please enable your location service", Toast.LENGTH_LONG).show()
            }
        } else {
            RequestPermission()
        }
        Log.e(TAG, "Holder3 = $holder")
        return holder
    }

最佳答案

如前所述,您可以使用 suspendCoroutine 异步地 (悬浮式)等待完成。

suspend fun <T> Task<T>.await(): T {
    if (isComplete) {
        val e = exception
        return if (e == null) {
            if (isCanceled) {
                throw CancellationException(
                        "Task $this was cancelled normally.")
            } else {
                result
            }
        } else {
            throw e
        }
    }

    return suspendCancellableCoroutine { cont ->
        addOnCompleteListener {
            val e = exception
            if (e == null) {
                if (isCanceled) cont.cancel() else cont.resume(result)
            } else {
                cont.resumeWithException(e)
            }
        }
    }
}

// Usage:
try{
    val location = fusedLocationProviderClient.lastLocation.await()
} catch(e:Exception){
    //handle exception
}

// do something with location, that should be executed after location has fetched
如果不运行代码以在协程内部等待,则可以将runBlocking的代码包装到同步的等待中(通过阻止当前线程)。
val location = runBlocking { fusedLocationProviderClient.lastLocation.await() }
// do something with location, that should be executed after location has fetched

关于android - 如何让编译器等待OnCompleteListener Kotlin,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63802432/

相关文章:

java - 默认情况下所有 Swing 组件都在 EDT 上运行吗?

android - 如何将 Room TypeConverter 应用于实体的单个字段?

java - Spring Data 与 JPA 2.2 resultStream 到 Kotlin 的 Flow

android - 如何在 DataBinding Android 的 BindingAdapter 方法中提供默认值

android - InputMethodService 中有两个 InputConnection 变量?

android - 无法在 AndEngine 中加载 Sprite

android - 在创建 android 通知时,在 PendingIntent 中使用 FLAG_UPDATE_CURRENT 时会重复 Intent 额外内容

javascript - 为 Android 应用程序创建动态雷达

合并图像时 C# 线程锁错误

c++ - 在多文件项目中启动线程