3

Say I have a Flutter app with two screens - screen A and screen B. Screen A is just a ListView that displays a list of items but needs to perform a network call whenever the list changes and then update the list. Screen B can modify the list of items but I want screen A to only perform the network call when screen A is in the foreground and being displayed. As far as I can tell, I cannot do this easily. Screen A is not disposed and reinitialized when navigating to and from screen B. It would very helpful if StatefulWidget had onForeground and onBackground methods to override, but they do not. This problem is not exclusive to navigation either, but this same problem presents itself when using PageView with full-screen pages. Is there some proper/standard way of implementing this?

My current setup is as follows: I let the parent widget to both screen A and B hold the list in a ValueNotifier and pass it to both screens when constructing them. Then, screen A listens for changes on the ValueNotifier and performs a network call whenever it does. So, in order to determine whether screen A is in the foreground/background, I will have to start/stop listening for changes before/after navigating. But I haven't started implementing this, as I think it will get complicated when widgets far down the widget tree trigger the navigation or other widgets need to know whether they're in the foreground/background.

Another option I've thought of is instead of observing for changes in the list, I could rather just return a result from screen B saying whether or not the list changed and react then. But I can think of many ways this can complicate my code as well since my real app involves more than just one dependency. I would have to create a custom result class for each screen containing a record of all the data that changed then it would be tedious if I want to add more data in the future. And how would I handle navigation to screen B then screen C? The result would have to be retained and passed down so screen A can react to changes made by screen C. I would also have to ensure all calls to Navigator.pop contained the result, and override back button presses to pop with the result. And I'd also have to ensure that the result makes it to the proper widgets that need to react to changes.

Am I just missing something simple to accomplish this? I am not the most experienced with Flutter and I wouldn't be surprised if there's some easy solution I haven't learned yet.

Edit: After some more testing, it appears AnimationController does something similar to what I need with the vsync parameter, in that it does not update when the State is in the background or when it is not being drawn. So, I could use SingleTickerProviderStateMixin on screen A's state, then use createTicker to create a Ticker, and then check if the Ticker.isTicking whenever the list changes. If it is ticking, screen A is in the foreground, otherwise it is in the background. Although I'm not sure if this is a good approach, since it appears Ticker's are really only used for Animations and there's nothing documented for a use case like mine.

Altherat
  • 701
  • 1
  • 13
  • 21
  • call **A**(parent) From **B**(child) and force it to refresh [check here](https://stackoverflow.com/a/51778268/4879683) – Mohamed Elrashid Aug 28 '19 at 20:49
  • That's not what I want to do. I do not want to refresh screen `A` (or perform the network call) when screen `B` is in the foreground. – Altherat Aug 28 '19 at 21:07
  • yes this work , that how i do it in my app ? – Mohamed Elrashid Aug 28 '19 at 21:08
  • here an examble [e004_flutter_listview_crud_app_using_nonsecure_rest_api/main.dart at master · elrashid-flutter-examples/e004_flutter_listview_crud_app_using_nonsecure_rest_api](https://github.com/elrashid-flutter-examples/e004_flutter_listview_crud_app_using_nonsecure_rest_api/blob/master/lib/main.dart) – Mohamed Elrashid Aug 28 '19 at 21:09
  • 1
    Okay, I see what you're saying. But that's basically the same as returning a result from screen `B`. It would work for apps with a simple widget tree and with a few screens like in your example, but will get more complicated when you add widgets that initiate navigation or have more screens. In your example, if `TaskAddPageWidget` navigated to another screen which modified the tasks, you have to ensure `TasksPageWidget` calls `refresh` only when both screens are finished. It would be a lot easier to observe the tasks, and only `refresh` when the tasks change and the list is in the foreground. – Altherat Aug 28 '19 at 21:47
  • ☺your are wright ✔ , did you consider using ***package:provider*** it will make you like easier for complex app with shared state – Mohamed Elrashid Aug 28 '19 at 21:56

0 Answers0