首页 > 解决方案 > Kotlin take(int).toList() 省略第一个元素

问题描述

我有一个测试 LiveData 每 2 秒发出一次项目。我将其转换为 flow 并在其上调用 take(3).toList()。

val list = newLiveData
            .asFlow()
            .onEach {
                println("Item ${it.status}")
            }
           .take(3)
           .toList()

println(list.joinToString {  "${it.status} " })

该 liveData 的实现使其首先发出 LOADING,然后继续发出 SUCCESS,所以我期待在列表中看到:

LOADING, SUCCESS, SUCCESS

但由于某种原因,它只返回

Item LOADING
Item SUCCESS
Item SUCCESS
SUCCESS , SUCCESS , SUCCESS 

奇怪的是,它会在 onEach 中打印正确的值,如果我用“first()”替换“take(3)”,我确实得到了正确的 LOADING 状态。

有没有人经历过这种行为?它对我来说看起来不太合适,所以如果它不是已知案例,我会打开一个错误报告。

标签: androidkotlinandroid-livedata

解决方案


所以事实证明它发生了,因为我的 LiveData 一直在修改一个对象并发送它,而不是每次都创建一个新实例。

我有一个类似于这样的 LiveData:

class EmittingLiveData : LiveData<StateData<Int>>() {

    init {
        value = StateData()
    }

    override fun observe(owner: LifecycleOwner, observer: Observer<in StateData<Int>>) {
        startEmitting()
        super.observe(owner, observer)
    }

    override fun observeForever(observer: Observer<in StateData<Int>>) {
        startEmitting()
        super.observeForever(observer)
    }

    private fun startEmitting() {
        GlobalScope.launch(Dispatchers.Unconfined) {
            value = value?.loading()

            async {
                while (this.isActive) {
                    delay(1000)
                    postValue(value?.success(0))
                }
            }.start()
        }
    }

}

并且不得不将发布价值更改为

postValue(StateData<Int>().success(0))

一个菜鸟 - 对象引用 - 问题,但我没想到会出现这种情况。所以也许其他人也会觉得这很有帮助:)

帮助我的学分转到qwwdfsad github 问题


推荐阅读