cpg*_*en2 3 android coroutine kotlin kotlin-coroutines
我正在尝试在我正在构建的天气应用程序中实现 SwipeToRefreshLayout。当用户滑动刷新时,应该更新ViewModel中的数据,然后相应地更新视图。
这是我的 CurrentWeatherFragment 的片段:
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel = ViewModelProviders.of(this, viewModelFactory)
.get(WeatherResponseViewModel::class.java)
pullToRefresh.setOnRefreshListener(this)
bindUI()
}
override fun onRefresh() {
viewModel = ViewModelProviders.of(this, viewModelFactory)
.get(WeatherResponseViewModel::class.java)
bindUI()
pullToRefresh.isRefreshing = false
}
private fun bindUI() = launch {
val currentWeather = viewModel.weather.await()
currentWeather.observe(this@CurrentWeatherFragment, Observer {
if (it == null) return@Observer
loading_icon.visibility = View.GONE
updateLocation("Raleigh")
updateDateToToday()
updateTemperatures(it.currently.temperature.roundToInt(),
it.currently.apparentTemperature.roundToInt(),
it.daily.data[0].temperatureMin.roundToInt(),
it.daily.data[0].temperatureMax.roundToInt())
updateDescription(it.currently.summary)
updateEnvironmentals((it.currently.humidity * 100).roundToInt(), it.currently.windSpeed.roundToInt())
updateWeatherIcon(it.currently.icon)
updateTempChart(it)
updatePrecipChart(it)
})
}
Run Code Online (Sandbox Code Playgroud)
我的视图模型:
class WeatherResponseViewModel (
private val forecastRepository: ForecastRepository,
unitProvider: UnitProvider
) : ViewModel() {
private val unitSystem = unitProvider.getUnitSystem()
val isMetric: Boolean
get() = unitSystem == UnitSystem.METRIC
val weather by lazyDeferred {
forecastRepository.getWeather()
}
}
Run Code Online (Sandbox Code Playgroud)
和我的 lazyDeferred 实现:
fun <T> lazyDeferred(block: suspend CoroutineScope.() -> T): Lazy<Deferred<T>> {
return lazy {
GlobalScope.async {
block.invoke(this)
}
}
}
Run Code Online (Sandbox Code Playgroud)
目前,使用此设置,在应用启动或切换到片段时加载片段时,将调用 ViewModel 中的 forecastRepository.getWeather() 函数,但在滑动刷新时,不会调用它。如何让 ViewModel 中的天气变量更新,以便视图可以观察到变化?
首先,你的代码中有一些关于 Coroutine 和 ViewModel 的错误实现。
不要在onRefresh.
相反,当 SwipeRefreshLayout 被拉出时,只需在你的视图模型中创建和调用 refresh 方法。
如果可以,请不要在您的应用程序中使用 GlobalScope。
它可能导致工作泄漏并且不遵循结构化并发规则。
相反,使用coroutineScope{}块。
不要使用LifecycleOwner的Fragment观察LiveData的片段。它可以为 生成重复的观察者LiveData。
相反,使用viewLifecycleOwner片段的实例。
这是因为当片段在返回堆栈中恢复时,片段的视图被重新创建,但片段。
如果您将观察者生命周期与片段中的视图相匹配,Ovserver则视图销毁后 s 将不会保留。
刷新方式
不要使用惰性块。像@Stanislav Bondar's answer一样似乎没用。
| 归档时间: |
|
| 查看次数: |
3418 次 |
| 最近记录: |