Does Dart/Flutter have the concept of weak references?

4,297

Solution 1

Dart doesn't provide weak reference feature.

An Expando has a weak reference behavior though. Not sure if this is of use in your use case.

I sometimes use a Mixin that provides a list where I can add subscriptions and a dispose methode that cancels all subscriptions and add it to widgets and other classes where I need it.

Solution 2

As of 2020, I'd like to add to Günter's answer that I've just published a package that goes as close as possible to a weak-reference by implementing a weak-map and a weak-container, as well as cache functions that take advantage of weak references.

It's much easier to use than an Expando (it uses Expando internally).

Share:
4,297
hunter
Author by

hunter

Updated on December 04, 2022

Comments

  • hunter
    hunter over 1 year

    I'm in the early stages of learning Dart & Flutter. I'm looking at how to implement an eventbus, which works fine, but I've noticed that Widgets (and/or their associated state) hold a strong reference to the (global) eventbus, causing a memory leak. The solution is to cancel the subscription in the widget-state's dispose method, but I'd like to know if there's a better approach (I'm coming from Swift which allows variables to be declared as 'weak').

    EDIT

    I ended up subclassing the state as follows... any better suggestions?

    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}');
      }
    }