51

I am working on a Flutter app and need to pop the screen. I tried initState() method but no luck. initState() gets called when I open a class for the first time.

Do we have an equivalent of Android onResume() method in Flutter?

Any ideas?

Satish Saini
  • 2,880
  • 3
  • 24
  • 38
  • 1
    None of the answers below provide an exact equivalent. I wrote an answer that covers _all_ equivalent lifecycle events to iOS and Android. https://stackoverflow.com/a/71279848/1759443 – Kyle Venn Mar 18 '22 at 17:47

4 Answers4

79

You can use the WidgetsBindingObserver and check the AppLifeCycleState like this example:

class YourWidgetState extends State<YourWidget> with WidgetsBindingObserver {

  @override
  void initState() {
    WidgetsBinding.instance?.addObserver(this);
    super.initState();
  }

 
  @override
  void dispose() {
    WidgetsBinding.instance?.removeObserver(this);
    super.dispose();
  }
  

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
       //do your stuff
    }
  }
}

Take in mind that It will called every time you open the app or go the background and return to the app. (if your widget is active)

If you just want a listener when your Widget is loaded for first time, you can listen using addPostFrameCallback, like this example:

class YourWidgetState extends State<YourWidget> {

  _onLayoutDone(_) {
    //do your stuff
  }

  @override
  void initState() {
    WidgetsBinding.instance?.addPostFrameCallback(_onLayoutDone);
    super.initState();
  } 

}

Info : https://docs.flutter.io/flutter/widgets/WidgetsBindingObserver-class.html

Update: Null safety compliance

Karim
  • 962
  • 7
  • 10
diegoveloper
  • 93,875
  • 20
  • 236
  • 194
  • Does `addPostFrameCallback` and `LayoutBuilder`'s `build()` method receive the control/focus at the same time? – CopsOnRoad Nov 03 '18 at 06:15
  • No, addPostFrameCallback is called after the first render of the tree. – diegoveloper Nov 03 '18 at 06:24
  • Try adding `?` for null-safety.... in `WidgetsBinding.instance?.addObserver(this);` and `WidgetsBinding.instance?.removeObserver(this);` – kosiara - Bartosz Kosarzycki May 10 '21 at 19:49
  • 1
    AppLifecycleState.resumed has different behavior for iOS and Android. On android its called only when we come from background to foreground (not on screen load). For iOS its called on screen load too. Is this intended? – Uzair Aslam May 27 '21 at 11:22
  • https://stackoverflow.com/a/58504433/5219642 you can check this for more detail – Amit Oct 25 '21 at 11:53
  • I just tried this approach on my stateful widget. Unlike onResume, it doesn't seem to get called when a new screen is popped from the stack and my widget comes back to focus. – Harsha Jun 21 '22 at 07:28
  • no it's only when you open a native view or you press home, you app is paused and you open you app again – diegoveloper Jun 22 '22 at 03:17
  • It's not the equivalent of Android's onResume. The code above only gets triggered when an app goes in background and back. – idk.the.name Mar 20 '23 at 18:31
44

If you go to another page, then is called when you comeback

Navigator.push(
  context,
  MaterialPageRoute(
    builder: (context) => SecondPage(),
  ),
).then((value) {
  _refreshFirstPage();
});
Álvaro Agüero
  • 4,494
  • 1
  • 42
  • 39
  • 2
    This works great thanks. In my case, I had to force a state refresh when coming back from a pop event. I couldnt use a push event and had to use pop, which does not have a then method. So this worked perfectly. – Janpan Apr 17 '21 at 13:00
  • 3
    If I can navigate to five different pages from page A, then I need to add `_refreshFirstPage();` at 5 places. I wish there was a better way of doing this. – Rohan Taneja Jul 28 '21 at 11:24
  • This is the best solution for my case. I need to refresh the main page after my app user come back from a detail page. She might have performed something on the detail page, which require some liitle part of the main page to be updated. I don't need real 'onResume' equivalent since there's nothing to update anyway, if my app user opened something other than my app's detail page. – Daniel Wu May 25 '23 at 07:50
11

You can accomplish this by registering a didChangeAppLifecycleState observer:

class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(final AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
      setState(() {
        // ...your code goes here...
      });
    }
  }

  @override
  Widget build(final BuildContext context) {
    // ...your code goes here...
  }
}

See WidgetsBindingObserver for more information.

Arto Bendiken
  • 2,567
  • 1
  • 24
  • 28
6

Use focus_detector more information can see visibility_detector

Get notified every time your widget appears or disappears from the screen.

Similar to onResume()/onPause() on Android and viewDidAppear()/viewDidDisappear() on iOS.

Focus Detector fires callbacks for you whenever something happens to take or give your widget focus. Such an event might be, for instance, the user:

Navigating to/from another screen;

Turning the device’s screen on/off while your widget is visible;

Switching to/from another app while your widget is visible;

Scrolling your widget in/out the screen;

@override
Widget build(BuildContext context) =>
    FocusDetector(
      onFocusLost: () {
        logger.i(
          'Focus Lost.'
          '\nTriggered when either [onVisibilityLost] or [onForegroundLost] '
          'is called.'
          '\nEquivalent to onPause() on Android or viewDidDisappear() on iOS.',
        );
      },
      onFocusGained: () {
        logger.i(
          'Focus Gained.'
          '\nTriggered when either [onVisibilityGained] or [onForegroundGained] '
          'is called.'
          '\nEquivalent to onResume() on Android or viewDidAppear() on iOS.',
        );
      },
      onVisibilityLost: () {
        logger.i(
          'Visibility Lost.'
          '\nIt means the widget is no longer visible within your app.',
        );
      },
      onVisibilityGained: () {
        logger.i(
          'Visibility Gained.'
          '\nIt means the widget is now visible within your app.',
        );
      },
      onForegroundLost: () {
        logger.i(
          'Foreground Lost.'
          '\nIt means, for example, that the user sent your app to the background by opening '
          'another app or turned off the device\'s screen while your '
          'widget was visible.',
        );
      },
      onForegroundGained: () {
        logger.i(
          'Foreground Gained.'
          '\nIt means, for example, that the user switched back to your app or turned the '
          'device\'s screen back on while your widget was visible.',
        );
      },
      child: Container(),
    );
朱相卿
  • 61
  • 1
  • 2