我正处于学习Dart和Flutter的早期阶段。我正在研究如何实现 eventbus,它工作得很好,但我注意到 Widget(和/或其关联状态)持有对(全局)事件总线的强引用,导致内存泄漏。解决方案是取消 widget-state 的 dispose 方法中的订阅,但我想知道是否有更好的方法(我来自 Swift,它允许将变量声明为“弱”)。
编辑
我最终对状态进行了子类化,如下...还有更好的建议吗?
abstract class CustomState<T extends StatefulWidget> extends State {
List<StreamSubscription> eventSubscriptions = [];
void subscribeToEvent(Object eventClass, Function callback) {
StreamSubscription subscription = eventBus.on(eventClass).listen(callback);
eventSubscriptions.add(subscription);
}
void dispose() {
super.dispose();
eventSubscriptions.forEach((subscription) => subscription.cancel());
eventSubscriptions = null;
}
}
class MyEvent {
String text;
MyEvent(this.text);
}
class _MyHomePageState extends CustomState<MyHomePage> {
@override
void initState() {
super.initState();
subscribeToEvent(MyEvent, onEventFired);
}
void onEventFired(event) {
print('event fired: ${event.runtimeType} ${event.text}');
}
}
Dart 不提供弱引用功能。
虽然 Expando 具有弱引用行为。 不确定这是否适用于您的用例。
我有时使用 Mixin,它提供了一个列表,我可以在其中添加订阅,以及一个 dispose 方法,该方法取消所有订阅并将其添加到小部件和其他我需要的类中。
自 dart 2.17 起,您可以使用 WeakReference。
任何包含在
WeakReference(obj)
中的对象都不会被垃圾回收。
您可以通过
target
属性访问该对象,当对象被垃圾回收时,该属性将变为 null
。
final myWeakRef = WeakReference(ExampleObj());
// access obj, may be null
print(myWeakRef.target);
截至 2020 年,我想在 Günter 的答案中补充一点,我刚刚发布了一个包,通过实现 weak-map 和 weak-container 来尽可能接近弱引用,如以及利用弱引用的缓存函数。
它比 Expando 更容易使用(它内部使用 Expando)。
我的项目中需要一个可迭代的 WeakHashMap,因此我使用 WeakReference 和 Finalizer 类实现了一个。这是包裹:
除了键是WeakReferenced外,它与其他Dart HashMap具有相同的属性和方法。