如何监听Kotlin MutableList的元素变更并执行指定函数?
监听MutableList增删操作并执行指定函数的方案
针对你的需求,这里提供几种可行的实现方式,同时回答你关于可观察可变列表的问题:
一、自定义封装MutableList(轻量无依赖)
自己写一个类包装原生的MutableList,重写所有会修改列表的方法,在实际完成增删操作后触发foo函数:
class ObservableMutableList<T>(private val delegate: MutableList<T> = mutableListOf()) : MutableList<T> by delegate { // 重写所有修改列表的方法,触发foo override fun add(element: T): Boolean { val success = delegate.add(element) if (success) foo() return success } override fun add(index: Int, element: T) { delegate.add(index, element) foo() } override fun addAll(elements: Collection<T>): Boolean { val success = delegate.addAll(elements) if (success) foo() return success } override fun addAll(index: Int, elements: Collection<T>): Boolean { val success = delegate.addAll(index, elements) if (success) foo() return success } override fun remove(element: T): Boolean { val success = delegate.remove(element) if (success) foo() return success } override fun removeAt(index: Int): T { val removed = delegate.removeAt(index) foo() return removed } override fun removeAll(elements: Collection<T>): Boolean { val success = delegate.removeAll(elements) if (success) foo() return success } override fun retainAll(elements: Collection<T>): Boolean { val success = delegate.retainAll(elements) if (success) foo() return success } override fun clear() { if (delegate.isNotEmpty()) { delegate.clear() foo() } } } // 使用方式 var questionPool: MutableList<String> = ObservableMutableList()
这种方式的优势是不需要依赖任何第三方库,完全自定义触发逻辑,只有当列表确实被修改时才会调用foo。
二、用Kotlin StateFlow实现可观察列表(适合协程场景)
如果你的项目用了协程,可以用MutableStateFlow包裹列表,通过更新StateFlow来触发监听,进而执行foo:
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch import kotlinx.coroutines.GlobalScope // 内部可变的StateFlow,外部暴露只读版本 private val _questionPool = MutableStateFlow(mutableListOf<String>()) val questionPool = _questionPool.asStateFlow() // 启动协程监听列表变化,触发foo init { GlobalScope.launch { questionPool.collect { foo() } } } // 封装增删方法,必须通过更新StateFlow触发监听 fun addQuestion(id: String) { val newList = _questionPool.value.toMutableList() if (newList.add(id)) { _questionPool.value = newList } } fun removeQuestion(id: String) { val newList = _questionPool.value.toMutableList() if (newList.remove(id)) { _questionPool.value = newList } }
这种方式适合需要异步处理列表变化的场景,还能在collect中对比前后列表的差异,做更复杂的逻辑处理。注意要根据实际业务管理协程的生命周期,避免内存泄漏。
三、Android平台专属:ObservableArrayList
如果你是在Android项目中开发,可以直接用系统提供的ObservableArrayList,它自带列表变化监听器:
import android.databinding.ObservableArrayList import android.databinding.ObservableList val questionPool: ObservableList<String> = ObservableArrayList() // 添加列表变化监听器,触发foo questionPool.addOnListChangedCallback(object : ObservableList.OnListChangedCallback<ObservableList<String>>() { override fun onChanged(sender: ObservableList<String>?) = foo() override fun onItemRangeChanged(sender: ObservableList<String>?, positionStart: Int, itemCount: Int) = foo() override fun onItemRangeInserted(sender: ObservableList<String>?, positionStart: Int, itemCount: Int) = foo() override fun onItemRangeMoved(sender: ObservableList<String>?, fromPosition: Int, toPosition: Int, itemCount: Int) = foo() override fun onItemRangeRemoved(sender: ObservableList<String>?, positionStart: Int, itemCount: Int) = foo() })
这种方案不需要自己封装方法,适合Android数据绑定的场景,系统会自动在列表增删改移时触发对应的回调。
关于可观察可变列表的说明
原生Kotlin标准库并没有提供现成的可观察MutableList,但可以通过上面几种方式实现:要么自己封装拦截修改操作,要么用数据流(StateFlow)包裹列表,Android平台则有官方的ObservableList实现。
内容的提问来源于stack exchange,提问作者234
相关产品推荐
相关产品推荐

