使用 Kotlin 从 Android 上 ViewModel 中的 LiveData 更新 ListView 中的元素
Posted
技术标签:
【中文标题】使用 Kotlin 从 Android 上 ViewModel 中的 LiveData 更新 ListView 中的元素【英文标题】:Update element in ListView from LiveData in ViewModel on Android using Kotlin 【发布时间】:2021-01-18 12:30:54 【问题描述】:我正在制作一个由单个活动组成的应用程序。
用户可以通过单击一个按钮来创建一个预定义大小的数组。通过另一个按钮,我希望使用各种算法对数组进行排序。
算法及其执行时间显示在ListView
中。请参阅下面的屏幕截图作为示例:
我的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
来自我的ViewModel
的allAlgorithms
是MutableList<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()
以获得正确的算法。
我试图在我的适配器中放置一个观察者,但我无法获得ViewModelProvider
,因为我没有找到访问 LifeCycleOwner 的方法。
我也尝试过更新我的allAlgorithm
列表,但它当然不会更新 UI。
我的问题:
如何使用 LiveData 更新我的 ListView? 有没有更好的方法来实现我想要实现的目标?【问题讨论】:
【参考方案1】:我以前也遇到过类似的情况。我想虽然适配器生命周期与活动生命周期紧密相关,所以我可以将 LifecycleOwner
传递给适配器并且它工作得很好
我什至在我的列表中插入了 500 多个 Item 来测试性能,每个列表项都持有一个 LiveData
观察者,我没有发现任何问题。
也许这不是最好的解决方案,但至少你可以试一试
【讨论】:
感谢您的回答。你能解释一下你是如何通过 lifeCycleOwner 的吗?另外,您是否在任何地方使用过 notifyDataSetChanged ?【参考方案2】:我犯了一个非常明显的错误,导致我的 notifyDataSetChanged() 不起作用:
在MyCustomAdapter
中,我没有传递MainActivityViewModel
的原始版本,而是在每个不智能的调用中实例化新的viewModel
。
简单的解决方法是将我的 MainActivityViewModel
实例传递给适配器,如下所示:
val adapter = MyCustomAdapter(this, viewModel)
listView.adapter = adapter
并相应地修改适配器:
class MyCustomAdapter(context: Context, vm: MainActivityViewModel): BaseAdapter()
并考虑了更改。
【讨论】:
以上是关于使用 Kotlin 从 Android 上 ViewModel 中的 LiveData 更新 ListView 中的元素的主要内容,如果未能解决你的问题,请参考以下文章
无法使用 Kotlin Retrofit 将数据从 Android 插入到 Mysql [重复]
Kotlin史上超强二合一,Kotlin从入门到精通+高级Kotlin强化实战(附Demo)