android MutableList未更新

wh6knrhe  于 2023-03-28  发布在  Android
关注(0)|答案(1)|浏览(207)

我尝试通过函数“addToArray”在LiveData中更新MutableList的值。但是当我尝试将LiveData观察到一个片段时,我得到null。发生了什么?请提供任何建议?!可能是,我需要在LiveData中更改一个类型?!但是,我应该选择什么?我使用ViewModelFactory初始化viewModel。

class MainViewModel(private val point: Int, private val index: Int) : ViewModel() {

    private var _arrayOne = MutableLiveData<MutableList<Int?>?>()
    val arrayOne: LiveData<MutableList<Int?>?> = _arrayOne

    fun addToArray(index: Int, point: Int) {
        val value = _arrayOne.value
        value?.add(point)
        _arrayOne.value = value
        Log.d("ViewModel", "$value")
    }
private lateinit var binding: FragmentMainBinding
    private var point = 0
    private var index = 0

    private val viewModelFactory: MainViewModelFactory by lazy {
        MainViewModelFactory(point, index)
    }
    private val viewModel by lazy {
        ViewModelProvider(this, viewModelFactory)[MainViewModel::class.java]
    }

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

        val array = initializeFirstParticipant()
        for (item in array) {
            item.setOnEditorActionListener { textView, i, keyEvent ->
                if (textView.text.toString().isEmpty()) {
                    textView.setBackgroundResource(R.drawable.background_outlined_red)
                    Toast.makeText(requireContext(), "Enter valid value!", Toast.LENGTH_SHORT)
                        .show()
                    true
                } else {
                    val point = Integer.parseInt(textView.text.toString())
                    val index = array.indexOf(item)
                    viewModel.addToArray(index, point)
                    Log.d("MainFragment", "Index is $index, value is $point")
                    viewModel.arrayOne.observe(viewLifecycleOwner, Observer {
                        Log.d("MainFragment", "Array is $it")
                    })
                    textView.setBackgroundResource(R.drawable.background_outlined)

                    false
                }
            }
        }
    }

    /* Return array of view for editing score for first participant */
    fun initializeFirstParticipant(): Array<TextView> {
        val tvArray = arrayOf<TextView>(
            binding.partOnePointTwo,
            binding.partOnePointThree,
            binding.partOnePointFour,
            binding.partOnePointFive,
            binding.partOnePointSix,
            binding.partOnePointSeven
        )
        return tvArray
    }
}`

I try to set Array instead List type Within LiveData, but it didn't help.     May be, I need to use another type within LiveData?!
kknvjkwl

kknvjkwl1#

你从来没有真正创建过一个MutableList放到你的LiveData中。注意你从来没有在代码中调用过mutableListOfarrayListOf()
也很少需要将LiveData的类型设置为可空,尤其是List,因为你可以使用空列表来表示没有数据。尽可能避免可空的东西,因为它会使代码更难处理。(在Java中,我们避免为空性,因为它使代码变得脆弱,即容易崩溃。Kotlin通过强制执行空检查来修复脆弱性,但这使得可空变量更难正确处理)。
如果可以的话,还应该使列表的类型不可为空。
首先,我将其更改如下:

private var _arrayOne = MutableLiveData<MutableList<Int>>(mutableListOf())
val arrayOne: LiveData<MutableList<Int>> = _arrayOne

然而,我还想提一下,在LiveData中使用MutableList通常是一个坏主意,原因如下:

***封装性差。**你是在向观察者(它在另一个类中)宣传,它有意义,可以直接修改列表的内容。
***无法检测到更改。**如果您的观察者将此列表传递给一个将以前的数据与新数据进行比较的类,例如ListAdapter(它这样做是为了优化其刷新方式,并提供移动或添加/删除项的自动动画),它将中断,因为您在告诉它新数据之前正在改变旧数据,因此它无法检测新旧之间的任何更改。

因此,最好使用只读列表。因此,您可以将代码更新为:

class MainViewModel(private val point: Int, private val index: Int) : ViewModel() {

    private var _arrayOne = MutableLiveData<List<Int>>(emptyList())
    val arrayOne: LiveData<List<Int>> = _arrayOne

    fun addToArray(index: Int, point: Int) {
        _arrayOne.value = _arrayOne.value.orEmpty() + point
        Log.d("ViewModel", "$value")
    }

上面的orEmpty()是一个简单的方法来处理LiveData.value总是返回一个可空的,即使类型是不可空的,在这个例子中,我们知道它永远不会是空的,但是我喜欢避免使用!!

相关问题