当前位置: 首页 > 知识库问答 >
问题:

如何使用 Kotlin 延迟加载协程刷新 ViewModel 数据?

赵昊阳
2023-03-14

我正在尝试在我正在构建的天气应用程序中实现SwipeToRe新鲜布局。当用户滑动刷新时,ViewModel中的数据应该更新,然后视图应该相应地更新。

这是我的货币天气片段的片段:

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)
        })
    }

我的视图模型:

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()
    }

}

我的lazyDeferred实现:

fun <T> lazyDeferred(block: suspend CoroutineScope.() -> T): Lazy<Deferred<T>> {
    return lazy {
        GlobalScope.async {
            block.invoke(this)
        }
    }
}

目前,通过此设置,forecastRepository。当在应用程序启动或切换到该片段时加载该片段时,会调用ViewModel中的getWeather()函数,但在滑动刷新时,不会调用该函数。如何更新ViewModel中的天气变量,以便视图可以观察到变化?

共有2个答案

吴同
2023-03-14

来自科特林委托财产:

惰性属性:仅在首次访问时计算值;

不要对可变数据使用< code>lazy

黄沈浪
2023-03-14

首先,您的代码中有一些关于协程和视图模型的错误实现。

> < li>

不要在< code>onRefresh中再次重新实例化ViewModel。

相反,只需在拉动SwipeRefreshLayout时在viewmodel中创建并调用refresh方法。

如果可能,不要在应用程序中使用GlobalScope。

它会导致工作泄漏,且不遵循结构化并发规则。

请改用< code>coroutineScope{}块。

不要使用Fra的来观察片段中的LiveData。它可以为LiveData生成重复的观察者。

请改用片段的 viewLifecycle Owner 实例。

这是因为当片段在后退堆栈中恢复时,片段的视图会重新创建,但片段。

如果将观察点生命周期与片段中的视图匹配,则在视图被取消后,Ovserver将不会保留。

刷新方式

不要用懒人块。好像和< code>@Stanislav Bondar的回答一样没用。

 类似资料:
  • 我目前面临的问题是如何处理聚合中实体之间的关联。 考虑以下示例: 现在,我们有一个,User“实体,也是我的聚合根。他可以有一个,Product”和多个,别名。我现在需要的是检索相关的,Product和,,域模型中的“按需别名”。用户由UserFactory创建,当从持久性数据创建实体时,可以单独使用,也可以在UserRepository中使用。 这样做的原因是因为我们的业务逻辑(如您在示例中看到

  • 我正在使用slick.js构建一个旋转木马。但是,即使我将属性从更改为,在我滚动到该图像之前,图像仍然会被加载。我怀疑这是因为我的图像中有标记。我的问题是如何防止浏览器加载响应图像,或者如何正确地延迟加载响应图像。 这是我的img标签的样本

  • 描述 (Description) 延迟加载可应用于图像,背景图像和淡入效果,如下所述 - 对于图像 要在图像上使用延迟加载,请按照给定的步骤进行操作 - 使用data-src属性而不是src属性来指定图像源。 将类lazy添加到图像。 <div class = "page-content"> ... <img data-src = "image_path.jpg" class = "l

  • 我正在使用Mika Tuupola的jQuery延迟加载。 是否可以在每次延迟加载图像后调用函数。 我打算做的是跟踪图像的浏览次数。因此,如果图像是延迟加载的,这意味着用户已经看到了图像,我将通过在后台执行HTTP GET,将数据库中的计数器增加1。

  • 问题内容: 我在JPA实体中的延迟加载属性有问题。我读过许多类似的问题,但它们与spring或hibernate有关,并且他们的后代不适用或没有帮助。 该应用程序是在Wildfly应用程序服务器上运行的JEE和JPA2.1。有两个实体,DAO会话bean和servlet将它们放在一起: 当我运行此代码时,它失败并显示: 我对WebLogic / JPA1使用了非常相似的模式,并且运行平稳。任何的想

  • 问题内容: 我想知道在node.js中使用是否等效于延迟加载? 例如,如果我有一个函数需要代码中其他任何地方都不需要的特定node.js包,那么我最好在该函数内部使用它,以便仅在调用该函数时才包含所需的包。 我还不确定是否会由于缺乏对node.js架构的了解而在性能方面有所改善?我想它每次与服务器的连接都会使用更少的内存。但是,当它必须读取程序包时,它会增加磁盘的I / O吗,还是将其添加到内存中