I want to add a Listener when the widget/state is visible and remove myself from the Listener when I leave the route.

But if the user clicks on the back button and returns to the current widget/state, I want to do the same thing again.

Currently initState, didChangeDependencies, didUpdateWidget and build are NOT called when the user clicks back from the next page, therefore I cannot detect when the user is returning and the widget was loaded from cache.


Solution 1: Kernel James

After much poking around the API, I've discovered that ModalRoute and RouteObserver is what I want.

https://api.flutter.dev/flutter/widgets/ModalRoute-class.html https://api.flutter.dev/flutter/widgets/RouteObserver-class.html

If I just want to check if the current route is active I can call isCurrent on ModalRoute.of(context):

void onNetworkData(String data) {
  if (ModalRoute.of(context).isCurrent) {
    setState(() => list = data);
  }
}

If I want to listen to route load/unload, I just create it and serve it up the hood with Provider like this:

class HomePage extends StatelessWidget {
  final spy = RouteObserver<ModalRoute<void>>();
  build(BuildContext context) {
    return Provider<RouteObserver<ModalRoute<void>>>.value(
      value: spy,
      child: MaterialApp(
        navigatorObservers: [spy],      
      ),
    );
  }
}

Then somewhere in another widget:

class _AboutPageState extends State<AboutPage> with RouteAware {
    RouteObserver<ModalRoute<void>>? spy;

  void didChangeDependencies() {
    super.didChangeDependencies();
    spy = context.read<RouteObserver<ModalRoute<void>>>();
    spy.subscribe(this, ModelRoute.of(context)!);
  }

  void dispose() {
    spy.unsubscribe(this);
    super.dispose();
  }

  void didPush() => attachListeners();
  void didPopNext() => attachListeners();
  void didPop() => removeListeners();
  void didPushNext() => removeListeners();

  attachListeners() {
  }

  removeListeners() {
  }
}