【发布时间】:2021-10-10 18:05:24
【问题描述】:
我正在学习 android 开发,我决定使用来自名为 open water map 的服务的 api 构建一个天气应用程序。不幸的是,我遇到了以下问题:
为了获取通缉城市的天气数据,我首先需要执行获取地理坐标的请求。所以我需要做的是创建一个请求,等到它完成,然后使用从第一个接收到的数据执行另一个请求。
这是我的位置视图模型的样子:
class LocationViewModel constructor(private val repository: WeatherRepository): ViewModel() {
val location = MutableLiveData<List<GeocodingModel>>()
private val API_KEY = „xxxxxxxxxxxxxxxxxxxxxxxxx”
fun refresh() {
CoroutineScope(Dispatchers.IO).launch {
// call fetch location here in coroutine
}
}
private suspend fun fetchLocation(): Response<GeocodingModel> {
return repository.getCoordinates(
"Szczecin",
API_KEY
)
}
}
这就是我的天气视图模型的样子”
class WeatherSharedViewModel constructor(private val repository: WeatherRepository): ViewModel() {
private val API_KEY = „xxxxxxxxxxxxxxxxxxxxxxxxx”
val weather = MutableLiveData<List<SharedWeatherModel>>()
val weatherLoadError = MutableLiveData<Boolean>()
val loading = MutableLiveData<Boolean>()
fun refresh(lat: String, lon: String) {
loading.value = true
CoroutineScope(Dispatchers.IO).launch {
// call fetchWeather here in coroutine
}
loading.value = false
}
private suspend fun fetchWeather(lat: String, lon: String): Response<SharedWeatherModel> {
return repository.getWeather(
lat,
lon,
"minutely,hourly,alerts",
"metric",
API_KEY
)
}
}
我以这种方式在片段中使用两个视图模型:
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
val weatherService = WeatherApi.getInstance()
val repository = WeatherRepository(weatherService)
locationViewModel = ViewModelProvider(requireActivity(), ViewModelFactory(repository)).get(LocationViewModel::class.java)
weatherViewModel = ViewModelProvider(requireActivity(), ViewModelFactory(repository)).get(WeatherSharedViewModel::class.java)
locationViewModel.refresh()
Log.d(TAG, "lat: ${locationViewModel.location.value?.get(0)?.get(0)?.lat.toString()}, lon: ${locationViewModel.location.value?.get(0)?.get(0)?.lon.toString()}")
weatherViewModel.refresh(
locationViewModel.location.value?.get(0)?.get(0)?.lat.toString(),
locationViewModel.location.value?.get(0)?.get(0)?.lon.toString()
)
val weatherList = view?.findViewById<RecyclerView>(R.id.currentWeatherList)
weatherList?.apply {
layoutManager = LinearLayoutManager(context)
adapter = currentWeatherAdapter
}
val cityList = view?.findViewById<RecyclerView>(R.id.currentCityList)
cityList?.apply {
layoutManager = LinearLayoutManager(context)
adapter = currentLocationAdapter
}
observerLocationViewModel()
observeWeatherViewModel()
}
因此,在启动时,两个模型都会刷新,这意味着请求已发出。我试图以某种方式同步这些调用,但我最后一次尝试结束了传递给天气视图模型的刷新方法的数据为空。所以问题是两个协程一个接一个地启动,第一个没有等待第二个。
主要问题:协程中有同步机制吗?只要第一个未完成,我可以启动一个协程并等待启动第二个协程?
【问题讨论】:
标签: android kotlin mvvm retrofit2 kotlin-coroutines