LiveData списка уведомляет наблюдателей без вызова setValue или postValue - PullRequest
0 голосов
/ 09 июля 2019

У меня есть MutableLiveData, как в моей модели представления:

val liveData = MutableLiveData<ArrayList<*>>()‍‍‍‍‍

Я добавляю результаты вызова конечной точки к этому LiveData, например:

liveData.value?.addAll(myList)

Насколько я знаю, MutableLiveData не должен уведомлять, что это Observer с, если вы не сделаете setValue или postValue с ним, но в этот момент, когда мой код выполняется, Observer с уведомляются об изменении.

Как это возможно?


Обновление:

Я столкнулся с еще более странным поведением, этот тест проходит, но список печатается один раз: []

    @Test
    fun `strange live data behavior`() {
        val myLiveData = MutableLiveData<ArrayList<Int>>()
        val observer = mock() as Observer<ArrayList<Int>>
        myLiveData.observeForever(observer)
        myLiveData.observeForever { println(it) }
        myLiveData.value = ArrayList()
        verify(observer).onChanged(ArrayList())
        myLiveData.value?.addAll(listOf(1, 2, 3, 4))
        val result = ArrayList<Int>()
        result.add(1)
        result.add(2)
        result.add(3)
        result.add(4)
        verify(observer).onChanged(result)
    }

1 Ответ

2 голосов
/ 09 июля 2019

Когда LiveData отправляет уведомление, LiveData не отправляет копию элемента. Вместо этого он просто передает ссылку на тот же экземпляр, который содержит.

Это означает, что если вы изменили данные внутри LiveData следующим образом:

myLiveData.value?.addAll(listOf(1, 2, 3, 4))

Объект ArrayList, который ранее получил наблюдатель, также будет изменен без вызова Observer.onChanged(), вызванного , просто потому, что это один и тот же объект. Вот почему использование изменяемого объекта в LiveData или любом Наблюдателе / ​​реактивном паттерне, как правило, не очень хорошая идея.

Чтобы убедиться, что onChanged() действительно вызывается только один раз, добавьте эту строку в конце теста:

    @Test
    fun `strange live data behavior`() {
        val myLiveData = MutableLiveData<ArrayList<Int>>()
        val observer = mock() as Observer<ArrayList<Int>>
        myLiveData.observeForever(observer)
        myLiveData.observeForever { println(it) }
        myLiveData.value = ArrayList()
        verify(observer).onChanged(ArrayList())
        myLiveData.value?.addAll(listOf(1, 2, 3, 4))
        val result = ArrayList<Int>()
        result.add(1)
        result.add(2)
        result.add(3)
        result.add(4)
        verify(observer).onChanged(result)

        // Below should pass because onChanged is only called once.
        verify(observer, times(1)).onChanged(any()) 
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...