使用Kotlin在Android上的ViewModel中从LiveData更新ListView中的元素,

问题描述

我正在制作一个由单个活动组成的应用。

用户可以通过单击按钮来创建预定义大小的数组。还有另一个按钮,我希望使用各种算法对数组进行排序。

算法及其执行时间显示ListView中。请参见以下屏幕截图作为示例:

example of the activity at launch

我的listView是在MainActivity中创建的:

listView.adapter = MyCustomAdapter(this)

以及下面的适配器代码

class MyCustomAdapter(context: Context): BaseAdapter() {

    private val mContext: Context = context

    val names = MainActivityviewmodel().allAlgorithms

    override fun getCount(): Int {
        return names.size
    }

    override fun getItem(p0: Int): Any {
        return names[p0]
    }

    override fun getItemId(p0: Int): Long {
        return p0.toLong()
    }

    override fun getView(p0: Int,p1: View?,p2: ViewGroup?): View {

        val layoutInflater = LayoutInflater.from(mContext)
        val row = layoutInflater.inflate(R.layout.row_algorithm,p2,false)

        val nameTextView = row.findViewById<TextView>(R.id.algoName)
        nameTextView.text = names[p0].name

        val timer = row.findViewById<TextView>(R.id.timer)
        timer.text = names[p0].time

        return row
    }
}
来自我的allAlgorithms

viewmodelMutableList<Algorithm>

Algorithm类:

class Algorithm(var name: String,var time: String = "0.00 sec")

目前,此MutableList<Algorithm>使用listof(varIoUs algo names)进行了初始化。这意味着时间将保留为认值。

现在,当用户单击开始基准测试按钮时,在我的viewmodel调用函数

private var _executionTime = mutablelivedata<Long>(timer)
val executionTime: LiveData<Long>
    get() = _executionTime

private var _index = mutablelivedata(0)
val index: LiveData<Int>
    get() = _index

fun startBench() {
    for ((i,v) in names.withIndex()) {
        _executionTime.value = measureTimeMillis {
            arr.sort() // is the arr generated by clicking the button
        }
        _index.value = i
    }
}

稍后,我将为每种算法制作不同的功能,但现在我希望将ListView更新为executionTime.value()以使用正确的算法。

我尝试将观察者放入适配器中,但是由于找不到访问LifeCycleOwner的方法,因此无法获得viewmodelProvider

我还尝试过更新allAlgorithm列表,但是当然不会更新UI。

我的问题:

  • 如何使用LiveData更新ListView?
  • 是否有更好的方法来实现我想要的目标?

解决方法

我以前也经历过类似的情况。我以为适配器的生命周期与活动的生命周期紧密相关,所以我可以将LifecycleOwner传递给适配器,并且效果很好

我什至在列表中插入了500多个Item来测试性能,每个列表项都拥有一个LiveData观察者,但是我没有发现任何问题。

也许这不是最佳解决方案,但至少您可以尝试一下

,

我犯了一个非常明显的错误,导致我的notifyDataSetChanged()无法正常工作:

MyCustomAdapter中,我通过每个不明智的呼叫来实例化新的MainActivityViewModel,而不是通过viewModel的原始版本。

简单的解决方法是将我的MainActivityViewModel实例传递给适配器,如下所示:

    val adapter = MyCustomAdapter(this,viewModel)
    listView.adapter = adapter

然后相应地修改适配器:

class MyCustomAdapter(context: Context,vm: MainActivityViewModel): BaseAdapter()

并考虑了更改。