Android Jetpack: наблюдение за ArrayList не работает - PullRequest
0 голосов
/ 09 июня 2018

Я хочу установить базовый ViewModel и сохранить ArrayList, который можно обновлять и, таким образом, наблюдать, сохраняя его как LiveData.

Проблема заключается в том, чтоприкрепленный фрагмент ViewModel не может обнаружить изменения в моем ArrayList при вызове .observe для него.Хотя, когда я отлаживаю приложение, я вижу, что ArrayList, называемый s2, действительно обновился.

Вот мой ViewModel:

class MainViewModel : ViewModel() {
    private val _s1 = MutableLiveData<String>()
    private val _s2 = MutableLiveData<ArrayList<String>>()
    val s1: LiveData<String>
        get() = _s1
    val s2: LiveData<ArrayList<String>>
        get() = _s2

    init {
        _s1.value = "HELLO WORLD"
        _s2.value = arrayListOf("")
    }

    fun populateList() {
        _s2.value?.clear()
        for (i in 10 downTo 1) {
            _s2.value?.add("$i bottles")
        }
    }
}

и прикрепленный фрагмент:

class MainFragment : Fragment() {

    companion object {
        fun newInstance() = MainFragment()
    }

    private lateinit var viewModel: MainViewModel

    private var message2TV: TextView? = null

    // ...

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)

        message2TV = view?.findViewById(R.id.message_2)

        viewModel.s1.observe(this, Observer {
            view?.findViewById<TextView>(R.id.message)?.text = it
        })

        viewModel.s2.observe(this, Observer {
            if (it != null && it.isNotEmpty()) {
                message2TV?.text = ""
                it.forEach { item -> message2TV?.append("\n$item") }
            }
        })

        message2TV?.setOnClickListener {
            viewModel.populateList()
        }
    }
}

Когда я отлаживал, я также обнаружил, что viewModel.s2.observe() больше не вызывается после нажатия View (и обновления ArrayList).Я могу заставить его отображать список, только если я изменю ориентацию экрана.

Пожалуйста, что мне здесь не хватает?

1 Ответ

0 голосов
/ 09 июня 2018

LiveData запускает обновления при вызове setValue или postValue для него, давая ему ссылку на новое значение.Он не может определить, изменяется ли объект, который он в данный момент содержит внутри, как в этом примере, где изменяемый список изменяется.

Как и сейчас, в вашем коде нет вызовов setValue:

_s2.value?.clear() // _s2.getValue()?.clear()
for (i in 10 downTo 1) {
    _s2.value?.add("$i bottles") // _s2.getValue()?.add(...)
}

Если вы хотите, чтобы он вызывал наблюдателя, вы можете сделать что-то вроде этого:

class MainViewModel : ViewModel() {
    private val _s2 = MutableLiveData<List<String>>()
    val s2: LiveData<List<String>>
        get() = _s2

    init {
        _s2.value = listOf("")
    }

    fun populateList() {
        _s2.value = listOf() // this is a setValue call
        for (i in 10 downTo 1) {
            // _s2.setValue(_s2.getValue?.plus("$i bottles")
            _s2.value = _s2.value?.plus("$i bottles")
        }
    }
}

Вы также можете продолжать использовать ArrayList, если хотите, изменить его, а затем вызватьsetValue снова с тем же значением, но, как вы уже видели, это более подвержено ошибкам:

_s2.value?.add("$i bottles")
_s2.value = _s2.value // _s2.setValue(_s2.getValue)))
...