繁体   English   中英

如何从 kotlin 协程中的函数返回 fusedLocationProviderClient().lastLocation 作为流

[英]How to return fusedLocationProviderClient().lastLocation as flow from a function in kotlin coroutines

我在做什么

所以我正在开发一个天气预报应用程序,我在其中使用 fusedLocationProviderClient.lastLocation 访问设备位置,我们大多数人都知道位置提供者返回一个任务,所以为此我使用协程 Deferred 这样每当任务完成时它就会给出我的设备位置请查看代码以便更好地理解

private fun getLastDeviceLocation(): Deferred<Location?> {
        return if (hasLocationPermission())
            fusedLocationProviderClient.lastLocation.asDeferred()
        else
            throw LocationPermissionNotGrantedException()
    }

我的问题是什么

但现在我希望我的位置是一个实时位置,因此我必须使用协程流,这样每当我的位置发生变化时,我就能够自动获取新位置的天气,但因为我是 kotlin 协程的新手,所以我我不确定如何实现这一目标以及我如何能够将流程与延迟一起使用,

谁能帮我解决问题,或者如果这不可行,请建议我做一些其他工作来实现我的目标 在此先感谢

如果要将Deferred转换为Flow

val lastLocationFlow: Flow<Location> = flow {
    emit(fusedLocationProviderClient.lastLocation.asDeferred().await())
}

flow是最基本的流构建器。 它需要一个可挂起的块作为参数,它负责发出值。 Deferred.await()将暂停执行,直到任务返回Location (或null )。 然后流程将发出值并完成。


如果要将requestLocationUpdates从 callback 转换为Flow ,可以使用callbackFlow

Eugen Pechanec对我很有帮助,以下是我如何通过将其注入视图模型来将其用作实现。 下面是完整的实现

LastLocationFeatureImpl.kt

@SuppressLint("MissingPermission")
class LastLocationFeatureImpl(
    private var fusedLocationProviderClient: FusedLocationProviderClient,
) : LastLocationFeature {

    override suspend fun currentLocation(): Flow<Location> {
        return lastLocationFlow
    }

    private val lastLocationFlow: Flow<Location> = flow {
        emit(fusedLocationProviderClient.lastLocation.asDeferred().await())
    }

}

最后位置特征.kt

interface LastLocationFeature {
    suspend fun currentLocation() : Flow<Location>
}

定位模块.kt

@Module
@InstallIn(SingletonComponent::class)
object LocationModule {

    @Singleton
    @Provides
    suspend fun provideLastKnownLocationFeature(lastLocationFeature: LastLocationFeature): Flow<Location> {
        return lastLocationFeature.currentLocation()
    }

    @Provides
    @Singleton
    fun provideLastKnownLocationImplementation(fusedLocationProviderClient: FusedLocationProviderClient): LastLocationFeature {
        return LastLocationFeatureImpl(fusedLocationProviderClient)
    }

    @Singleton
    @Provides
    fun provideFusedLocationService(@ApplicationContext context: Context): FusedLocationProviderClient {
        return LocationServices.getFusedLocationProviderClient(context)
    }

}

MapsVm.kt

@HiltViewModel
class MapsVm @Inject constructor(
    private var lastLocationFeature: LastLocationFeature,
) : ViewModel() {

    @SuppressLint("MissingPermission")
    fun mapReset() {
        viewModelScope.launch {
            lastLocationFeature.currentLocation().collect{ location ->
                val lastKnownLocation = LatLng(location.latitude, location.longitude)

            }
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM