此article显示了在一个观察器中使用多个处理程序的示例代码。我在下面的文章中给出了一个代码示例。但此代码中存在内存泄漏错误-处理程序被添加到可变列表,但不会从列表中删除,例如,当使用其中一个处理程序的对象从内存中删除时。
class WeatherStation {
val temperatureChanged = mutableListOf<(Int) -> Unit>()
var temperature: Int by Delegates.observable(0) { _, _, newValue ->
temperatureChanged.forEach{it(newValue)}
}
}
// ...
val weatherStation = WeatherStation()
// Adding observer to the list, but where is its removal???
weatherStation.temperatureChanged.add { temperature ->
println("Temperature changed: $temperature")
}如何修复它,或者有其他解决方案吗?我需要-这样当更改一个属性时,就会调用几个观察者。尝试使用LiveData会导致大量的difficulties。
发布于 2020-04-16 22:26:05
传统上,当某个东西订阅了其他东西时,它负责取消订阅自己。您可以通过使用IdentityHashMap来完成此操作:
class WeatherStation {
val temperatureChangedObservers = IdentityHashMap<Any, (Int) -> Unit>()
var temperature: Int by Delegates.observable(0) { _, _, newValue ->
temperatureChangedObservers.values.forEach { it(newValue) }
}
}
// ...
val weatherStation = WeatherStation()
weatherStation.temperatureChanged.add(this) { temperature ->
println("Temperature changed: $temperature")
}
// remove self as observer when going out of scope:
weatherStation.remove(this)我使用了IdentityHashMap而不是MutableMap或HashMap,所以我们不必担心两个不同的观察者可能具有对象相等性。
如果你想自动取消订阅,这样当你的片段或活动超出范围时,你就不必担心了,你可以要求观察者是LifecycleOwners,这样你就可以观察他们的生命周期。我没有测试这个:
class WeatherStation: LifecycleObserver {
private val temperatureChangedObservers = IdentityHashMap<LifecycleOwner, (Int) -> Unit>()
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun onObserverDestroyed(source: LifecycleOwner) {
temperatureChangedObservers.remove(source)
}
fun observeTemperature(observer: LifecycleOwner, action: (Int) -> Unit) {
temperatureChangedObservers[observer] = action
observer.lifecycle.addObserver(this)
}
var temperature: Int by Delegates.observable(0) { _, _, newValue ->
temperatureChangedObservers.values.forEach { it(newValue) }
}
}
// ...
val weatherStation = WeatherStation()
weatherStation.observeTemperature(this) { temperature ->
println("Temperature changed: $temperature")
}发布于 2020-04-17 12:15:29
感谢您向Tenfour04发送answer!我以他的回答为基础,创建了一个维护观察者列表的简单通用类。如果将LifecycleOwner用作键,则类支持自动取消订阅。这是LiveData的一个简单替代方案。
class Visor<T>(initialValue: T): LifecycleObserver {
private var value = initialValue
private val observers = WeakHashMap<Any, (T) -> Unit>()
fun subscribe(owner: Any, observer: (T) -> Unit) {
if (owner is LifecycleOwner)
owner.lifecycle.addObserver(this)
observers[owner] = observer
}
fun subscribeAndInvoke(owner: Any, observer: (T) -> Unit) {
add(owner, observer)
observer(value) // invoke
}
fun remove(key: Any) {
observers.remove(key)
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun onObserverDestroyed(owner: LifecycleOwner) {
remove(owner)
}
operator fun getValue(thisRef: Any?, prop: KProperty<*>): T = value
operator fun setValue(thisRef: Any?, prop: KProperty<*>, value: T) {
this.value = value
observers.values.forEach{it(value)} // invoke all observers
}
}
// example of using
class WeatherStation() {
var temperatureVisor = Visor<Int>(0)
var temperature: Int by temperatureVisor
// ...
}
// addition of the first observer
val weatherStation = WeatherStation()
weatherStation.temperatureVisor.subscribe(this) {
Log.d("Visor", "New temperature: $it")
}https://stackoverflow.com/questions/61251720
复制相似问题