首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >LocationManager.requestSingleUpdate和kotlin suspendCoroutine

LocationManager.requestSingleUpdate和kotlin suspendCoroutine
EN

Stack Overflow用户
提问于 2022-03-30 19:34:10
回答 1查看 307关注 0票数 1

我想使用LocationManager.requestSingleUpdate()获取设备的当前全球定位系统位置。下面的代码用于在kotlin挂起函数中包装对LocationManager的调用:

代码语言:javascript
运行
复制
private var locationManager =
        context.getSystemService(LOCATION_SERVICE) as LocationManager

@RequiresPermission("android.permission.ACCESS_FINE_LOCATION")
suspend fun getCurrentLocationPreS(): Coordinate? = suspendCoroutine {
    val handlerThread = HandlerThread("getCurrentLocation() HandlerThread")
    handlerThread.start()

    try {
        // Use of deprecated function is ok because we are pre android S
        locationManager.requestSingleUpdate(
            LocationManager.GPS_PROVIDER,
            { location ->
                handlerThread.quit()
                it.resume(
                    Coordinate(
                        location.latitude,
                        location.longitude
                    )
                )
            },
            handlerThread.looper
        )
    }
    catch (ex: Exception) {
        ex.printStackTrace()
        it.resumeWithException(ex)
    }
}

如您所见,我使用suspendCoroutine进行异步位置调用。这个实现对某些设备有效,但我在其他设备上有问题。有时,由于位置更新回调没有被调用,因此支持函数永远不会返回和等待。该应用程序还具有所需的权限,并且启用了GPS。

什么边情况会导致函数永远不会返回的状态?

Logcat不表示任何异常或其他错误。该应用程序也不会崩溃。唯一的症状是getCurrentLocationPreS()永远不会回来。

EN

回答 1

Stack Overflow用户

发布于 2022-04-01 16:42:26

仅仅因为GPS已启用并不意味着它正在正常工作。当你在室内或高楼大厦密集的地区时,信号可能很差。如果您查看requestSingleUpdate的实现,您将看到它使用的超时时间为30,因此,如果超时过期,您的回调将永远不会执行,您的协同线将无限期地被卡住。

我建议要么为这个调用使用超时,要么考虑使用FusedLocationProviderClient,这样您就可以以更安全的方式获得最后一个已知的位置。

我还建议使用Looper.getMainLooper(),与确保正确管理HandlerThread相比,临时切换到主线程的运行时开销可以忽略不计。

所以我对这个的看法是这样的:

代码语言:javascript
运行
复制
suspend fun getCurrentLocationPreS(): Coordinate? = withTimeoutOrNull(30.seconds){
    suspendCoroutine { cont ->
        try {
            // Use of deprecated function is ok because we are pre android S
            locationManager.requestSingleUpdate(
                LocationManager.GPS_PROVIDER,
                { location ->
                    cont.resume(
                        Coordinate(
                            location.latitude,
                            location.longitude
                        )
                    )
                },
                Looper.getMainLooper()
            )
        }
        catch (ex: Exception) {
            ex.printStackTrace()
            cont.resumeWithException(ex)
        }
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71683149

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档