Usage of didChangeAppLifecycleState - flutter

I have one didChangeAppLifecycleState method at the top hierarchy of the navigator. It's located at MyApp widget of main.dart which is extended for the whole app and it works as expected.
There comes another page i'd like to add didChangeAppLifecycleState again for the purpose of when resume and user is happened to be at that particular page, then do something. But unfortunately, the second one is never invoked.
My questions are:
can I have more than one didChangeAppLifecycleState which located in different pages?
what should I do to achieve what I want

Related

how to prevent PageView.builder building page I didnt enter yet or delete getxcontroller after I leave the page - flutter/GetXcontroller

sorry in advance if i didnt describe my question clearly:
I have several pages made by PageView.builder, while swiping these pages on main screen left and right, I found their initState is already working, and GetXController inside are also loading their data. I use Get.delete<Controller> while clicking back button and coming back to main screen to remove these data.
However, the state and data will bring back to main screen if I didnt activate Get.delete<Controller>, and therefore next time I come to this page, the state of page will be not default, for instance the button still keep pressed status.
So my question is how to prevent page.builder to build the widget before I come inside to this page, or how to delete getxcontroller if I am not in this page. Thanks a lot!
Try resetting the GetX by calling
Get.reset(); --> this will re-initialize controllers
Alternatively calling
Get.put(ControllerName()); in a build method will re-initialize the controller

Navigator pushReplacementNamed loads screen twice in Flutter app

Inside Flutter app I have MaterialApp with list of named routes and bottom navigation bar with few tabs. On one of tabs I have button with this code on tap
Navigator.of(context).pushReplacementNamed(MyRouteName);
For some reason target screen is loaded few times (it can be seen on screen) and it's initState() method is also called at least twice. Why is it happening and what can be done with it?
I've had the same problem too, I solved it by going back with Navigator.of (context).pop Actually, the solution may vary depending on your status as the route. I suggest you try alternative methods.

Determining if widget is in the foreground/background

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.

Tracking screen views in Flutter with Firebase Analytics

What is the best location for manually logging a screen view in Flutter with an analytics package (in my case I am using Firebase Analytics, eg. track screens)?
Looking at the Flutter lifecycle, it's not clear where it makes sense to track a screen view.
For a StatelessWidget, I think build() might make sense as I guess it's only called one time per screen view.
What about for a StatefulWidget though? In this case build() would not be useful as it could be called many times. Other candidates are initState(), createState() or the constructor which all appear to only be called once although I'm guessing they may all be called more than once per screen view as widgets up the hierarchy are re-built.
The answer is: it depends. For a StatelessWidget, it might be suitable to have an Analytics event in build(), but only if the parent widgets are not re-built frequently. For a StatefulWidget the same applies but you also have to factor in re-builds due to state change (which are, more than likely often).
Really, the safest path is not to call Analytics events in any parts of the widget lifecycle, but instead on the UI event that might trigger a screen, for example, an edit button that opens up an edit screen. However, the problem with that approach is that the screen might be opened from a variety of locations within the app (meaning you have to duplicate Analytics calls across all those locations).
This means the best option is probably to tie Analytics to PageRoute transitions so that it is called consistently whenever a page route is executed. This is demonstrated in the docs. This will miss tracking screens within a tab bar and other types of UI navigation but as the docs also say, one way to handle this is to implement RouteAware and subscribing it to FirebaseAnalyticsObserver (example tabs implementation).

Why does the initState method of each page in TabBarView gets called every time a tab is changed

I would like to do some startup work on a page and I decided to put it in the initState method of a page however I noticed that every time I switch a tab the initState method of various other pages included in the TabBarView get called even when those pages are not requested. Is this normal behavior ? Currently the way I am handling to determine if the page is actually requested to be displayed is by reading the index value of TabController then performing the necessary initState work if needed. My question is am I handling this mechanism properly and also does the initState of each page get in the TabBarView get called whenever the tab changes ?
Not so sure but I think what Flutter attempts to do is to ready nearby tab views (one before and after for example) so that when the user switches views it'll already be loaded and to minimize load times.