Android Jetpack : Observing ArrayList not working

标签 android arraylist kotlin android-jetpack android-livedata

我想设置一个基本的ViewModel并存储 ArrayList可以更新并因此观察,将其存储为 LiveData .

问题是 ViewModel 附加的 Fragment 在调用 .observe 时似乎无法检测到我的 ArrayList 中的更改。在上面。虽然当我调试应用程序时,我可以看到 ArrayList - 称为 s2 - 确实更新了。

这是我的 View 模型:

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")
        }
    }
}

和附加的 fragment :
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)后,不会再次调用。只有当我改变屏幕方向时,我才能让它显示列表。

请问,我在这里错过了什么?

最佳答案

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)))

关于Android Jetpack : Observing ArrayList not working,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50769888/

相关文章:

android - Mono.Linker.MarkException : Error processing method: 'System. 无效 AndroidX.RecyclerView.Widget.RecyclerView/LayoutManager

java - 性能循环 arrayList 与 POJO (JAVA)

java - Spring数据JPA/Hibernate "Unable to locate Attribute with the given name"

winapi - 如何初始化 LPBOOL? Kotlin Native 中的 Win32 Api

android - 通过 chrome Intent 将推荐人数据传递给 google play

android - 权限拒绝 : not allowed to send broadcast in android

android - 对于游戏,您会实现安全性还是可用性?

java - 操作++/-- 的参数无效

java - 从可比数组中删除项目

android - 广义函数以避免重复