Android Jetpack:观察 ArrayList 不工作
Android Jetpack: Observing ArrayList not working
我想设置一个基本的 ViewModel
并存储一个可以更新和观察的 ArrayList
,将其存储为 LiveData
。
问题是 ViewModel 的附加片段在调用 .observe
时似乎无法检测到我的 ArrayList 中的变化。虽然当我调试应用程序时,我可以看到名为 s2
的 ArrayList 确实已更新。
这是我的视图模型:
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()
}
}
}
当我调试时,我还发现在单击视图(和更新 ArrayList)后,viewModel.s2.observe()
不再被调用。我只有改变屏幕方向才能让它显示列表。
拜托,我在这里错过了什么?
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)))
我想设置一个基本的 ViewModel
并存储一个可以更新和观察的 ArrayList
,将其存储为 LiveData
。
问题是 ViewModel 的附加片段在调用 .observe
时似乎无法检测到我的 ArrayList 中的变化。虽然当我调试应用程序时,我可以看到名为 s2
的 ArrayList 确实已更新。
这是我的视图模型:
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()
}
}
}
当我调试时,我还发现在单击视图(和更新 ArrayList)后,viewModel.s2.observe()
不再被调用。我只有改变屏幕方向才能让它显示列表。
拜托,我在这里错过了什么?
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)))