Using Transformations.map instead of observeForever

826 Views Asked by At

I am doing my first internship and I was converting RX codes to LiveData in a project. At some point, I had to replace subscribe() functions with observeForever() + Globalscope(Dispatchers.Main) in some repositories but apparently using observeForever() is not the best thing to do and my internship mentor suggested me to use Transformations.map() instead .

I am not sure about how to use map() instead of observeForever in the following code (In a repository) :

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

What I understand from Transformations.map() function is that, it is used to map the value of a given LiveData object, just like the Map operator of ReactiveX

I tried this but doesn't seem to do what I want :

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

My question is how should I use Transformation.map() to avoid observeForever ?

DO SOMETHING : may be a livedataObject.postValue(it) if you need an example

Thanks in advance for replies.

1

There are 1 best solutions below

5
On

Transformations.map is intended to be used for transforming every element observed. So it doesn't have a conditional way to prevent an emission. By example:

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

That returns a LiveData<Int>

If you want to add conditions for making your live data emit only sometimes then you have to use 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
           }
        }
    }
     
}

The trick is the MediatorLiveData can access the value as a field so you can choose when to update it and when not to, also apply transformations in the process.

For using it the way you need to:

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

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

Then observe myMediator