【问题标题】:Using Transformations.map instead of observeForever [duplicate]使用 Transformations.map 而不是 observeForever [重复]
【发布时间】:2021-05-11 14:06:54
【问题描述】:

我正在做我的第一次实习,我正在一个项目中将 RX 代码转换为 LiveData。 在某些时候,我不得不在某些存储库中用 observeForever() + Globalscope(Dispatchers.Main) 替换 subscribe() 函数,但显然使用 observeForever() 并不是最好的事情,我的实习导师建议我使用 Transformations.map () 代替。

我不确定如何在以下代码中使用 map() 而不是 observeForever(在存储库中):

        //I am using Globalscope with Dispathers.Main otherwise I get "cannot observeForever in a background Thread error
        GlobalScope.launch(Dispatchers.Main){
            someBooleanLiveData.observeForever { 
                if (it) {
                    // DO SOMETHING
                } else {
                    // DO SOMETHING ELSE
                }
            }
        }

我从 Transformations.map() 函数中了解到的是,它用于映射给定 LiveData 对象的值,就像 ReactiveX 的 Map operator 一样

我试过了,但似乎没有做我想做的事:

        Transformations.map(someBooleanLiveData){
            if (it) {
                // DO SOMETHING
            } else {
                // DO SOMETHING ELSE
            }
        }

我的问题是我应该如何使用 Transformation.map() 来避免 observeForever ?

做某事:如果您需要示例,可能是 livedataObject.postValue(it)

提前感谢您的回复。

【问题讨论】:

  • Avoid GlobalScope(来自 Kotlin 的首席开发人员)
  • 这并不能真正回答我的问题^^,但它似乎真的很有用。我有空的时候会看一下(可能就在我找到问题的答案之后)
  • Transformations.map() 用于创建您将在其他地方观察到的新 LiveData。它并不真正适用于响应原始 LiveData 的值而执行某些操作。如果当前没有观察到它,则当源 LiveData 值更改时它不会做任何事情。 someBooleanLiveData 是否在您项目的其他任何地方被观察到?也许 LiveData 甚至不适合它。

标签: android kotlin android-livedata android-livedata-transformations


【解决方案1】:

Transformations.map 旨在用于转换观察到的每个元素。所以它没有一个有条件的方法来防止排放。举例:

Transformations.map(booleanLiveData) {
    if (it) 1 else 0
}

返回一个LiveData<Int>

如果您想添加使实时数据仅在某些时候发出的条件,那么您必须使用MediatorLiveData

class MyMediator : MediatorLiveData<SomeType>() {


    //we can create this wrapper method for convenience    
    fun addBooleanSource(booleanLiveData: LiveData<Boolean>) {
        //this method is already exposed and you can wrap it or do it in the invoker
        addSource(booleanLiveData) {
           if (it) {
                value = //do something
           }
        }
    }
     
}

诀窍在于MediatorLiveData 可以将value 作为字段访问,因此您可以选择何时更新它,何时不更新,还可以在此过程中应用转换。

以您需要的方式使用它:

        private val _myMediator = MyMediator()
        val myMediator: LiveData<YourType>
            get() = _myMediator

        GlobalScope.launch(Dispatchers.Main){
            _myMediator.addBooleanSource(someBooleanLiveData)
        }

然后观察myMediator

【讨论】:

  • 是的,我现在明白了。我非常专注于使用 Transformations.map() 来观察 LiveData 对象,我没有考虑过使用 MediatorLiveData,甚至一秒钟也没有。我猜在内存管理(线程使用等)方面,MediatorLiveData 与 Transformations.map() 非常相似。我可能可以使用 MediatorLiveData 做我想做的事。谢谢
  • @Oguzhan MediatorLiveDataTransformations.map()(在内部使用 MediatorLiveData)不会给你与问题中的原始代码完全相同的行为,因为它们在被观察之前是被动的。带有observeForever 的代码将对原始 LiveData 的每次发射执行其操作。但是没有足够的关于你的具体案例的信息来知道哪个更有意义。
  • 所以,为了完成我想要做的事情,我必须在代码中的某处观察 MediatorLiveData 或 Transformations.map() 返回的 LiveData。我理解正确吗?
  • @Oguzhan 问题是您在那里使用全局范围并且由于某种原因永远观察,所以很难猜出您为什么这样做。你不应该那样做。观察者应该这样做:被他人观察。不是为了听东西和更新东西。尽我所能更新我的答案。试试看FlowChannels
  • stackoverflow.com/questions/47515997/… 。我想我只是重新发布了一个已经被问到的问题,并且以某种方式验证了一个根本不是答案的答案。我将删除以发布并从 cmets 中查找内容。感谢您的回答
猜你喜欢
  • 2020-09-01
  • 2013-08-25
  • 2011-12-03
  • 2015-08-06
  • 2019-01-01
  • 1970-01-01
  • 2015-11-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多