简体   繁体   English

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

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

What i am doing我在做什么

So i am developing a weather forecast application in which i am accessing the device location using fusedLocationProviderClient.lastLocation and most of us knows that the location provider return a task, so for that i am using coroutines Deferred so that whenever the task got completed it gives me the device location please have a look upon the code for better understanding所以我正在开发一个天气预报应用程序,我在其中使用 fusedLocationProviderClient.lastLocation 访问设备位置,我们大多数人都知道位置提供者返回一个任务,所以为此我使用协程 Deferred 这样每当任务完成时它就会给出我的设备位置请查看代码以便更好地理解

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

What my problem is我的问题是什么

but now i want my location to be a live location so for that i have to use coroutines flow, so that whenever my location changes i'll be able to fetch weather for the new location automatically, but because i am new to kotlin coroutines i am not sure how to achieve that and how i can be able to use flow with deferred,但现在我希望我的位置是一个实时位置,因此我必须使用协程流,这样每当我的位置发生变化时,我就能够自动获取新位置的天气,但因为我是 kotlin 协程的新手,所以我我不确定如何实现这一目标以及我如何能够将流程与延迟一起使用,

can anyone please help me out or if this is not feasible do suggest me some other work aroung to achieve my goal Thanks in Advance谁能帮我解决问题,或者如果这不可行,请建议我做一些其他工作来实现我的目标 在此先感谢

If you want to convert Deferred to Flow :如果要将Deferred转换为Flow

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

flow is the most basic flow builder. flow是最基本的流构建器。 It takes a suspendable block as a parameter, that's responsible for emitting values.它需要一个可挂起的块作为参数,它负责发出值。 Deferred.await() will suspend execution until the task returns a Location (or null ). Deferred.await()将暂停执行,直到任务返回Location (或null )。 The flow will then emit the value and finish.然后流程将发出值并完成。


If you want to convert requestLocationUpdates from callback to Flow , you could use callbackFlow .如果要将requestLocationUpdates从 callback 转换为Flow ,可以使用callbackFlow

Eugen Pechanec was helpful for me, Here is how I used it as implementation by injecting it into the view model. Eugen Pechanec对我很有帮助,以下是我如何通过将其注入视图模型来将其用作实现。 Here is complete implementation below下面是完整的实现

LastLocationFeatureImpl.kt 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())
    }

}

LastLocationFeature.kt最后位置特征.kt

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

LocationModule.kt定位模块.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 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