Using LiveData without LifecycleObserver

时间:2018-11-27 00:55:23

标签: android kotlin observable android-livedata

I'm writing an app which is (attempting) to adhere to the MVVM design pattern. I'd like to observe changes to the model layer from other parts of that layer. For example

Let's say I'm exposing a list of objects from my database using room:

@Dao
interface MyDao {
    @Query("SELECT * FROM myTable")
    fun getAllElements(): LiveData<List<Element>>
}

I'd like to be able to observe changes like I normally would using a lifecycle owner using LiveData.observeForever(). Something like:

class BusinessLogicPartOfTheModel(private val myDao: MyDao) {
    private var allElements = listOf<Element>()

    init {
        myDao.getAllElements().observeForever { observedElements ->
            allElements = observedElements
        }
}

However, I'm finding that if I register an observer like that as well as a more standard observer in a ViewModel and Fragment like this:

class MyViewModel(private val myDao: MyDao) : ViewModel() {
    fun getAllElements(): LiveData<List<Elements>> {
        myDao.getAllElements()
    }
}

class MyFragment : Fragment() {
    private val myDao /* initialized here */
    private val myViewModel /* initialized here */
    private val logic = BusinessLogicPartOfTheModel(myDao)

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        val obs = Observer<List<Element>> {
             // do a thing
        }
        myViewModel.getAllElements.observe(viewLifeCycleOwner, obs)
    }
}

Only the observer in the fragment is called, and not the observer in the business logic object. I can successfully observe updates in the fragment and pass the events back down to the business logic, but that seems like an incredibly unnecessary level of indirection. Am I missing a step here or is this just unlikely to function the way I want it to?

1 个答案:

答案 0 :(得分:2)

您可能应该改用MediatorLiveData

MediatorLiveData通过将另一个LiveData添加到MediatorLiveData来接受其他事件。

您可以使用类似的

val mediatorLiveData = MediatorLiveData<Item>().apply {
    addSource(yourLiveData) {
        // do something here
    }
}

您还可以查看Transformations

Transformations具有Transformation.map()Transformation.switchMap()之类的方法,它们仅在内部使用MediatorLiveData