Keep scroll controller open with Get.offNamed - flutter-getx

i'm using Getx as state management
class ProductsController extends GetxController with StateMixin<Posts> {
ScrollController scrollController = ScrollController();
#override
void onInit() {
_getData();
scrollController = ScrollController()..addListener(_loadMore);
super.onInit();
}
_getData() async {}
_loadMore() async {}
#override
void onClose() {
scrollController.removeListener(_loadMore);
super.onClose();
}
}
and everything works perfectly, but for some reasons i need to navigate to same page as replacement by
Get.offNamed(Routes.products, prevent Duplicates: false);
but i note that this void
#override
void onClose() {
scrollController.removeListener(_loadMore);
super.onClose();
}
called and i lost the scroll in the bage ...
so how to keep scrollController open or how to initialize it again when navigate to the same page as replacement
or am i need to use another method to navigate to same page as replacement to it ??
thanks

Related

Call api after bage build in getx

Im using getx and i want to call api after bage build, because this api its not necessary part of the page build.. What i know is this way
#override
void initState(){
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_){
});
}
But what about getx best way ?
the Getx package offers lifecycle methods that are very convenient in you're cases, what you need here is to use the onReady(), which is called one frame after the onInit() is executed, you can say that its equivalent to the:
#override
void initState(){
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_){
// Here is the code which will be executed exactly after initState using StatefulWidget
});
}
you can use onReady() like this:
class TextController extends GetxController {
#override
void onInit() {
/*...*/
}
void onReady() {
// Here is the code which will be executed exactly after onInit using Getx
}
}

Reinitialize Getx scrollController when navigate to same page

I use Get.offNamed to navigate to same page _ but this method called
#override
void onClose() {
scrollController.removeListener(_loadData);
super.onClose();
}
As a result I lose page scrolling How do I reset the scrollController
the Controller :
class PostsController extends GetxController with StateMixin<Posts> {
ScrollController scrollController = ScrollController();
#override
void onInit() {
_getData();
scrollController = ScrollController()..addListener(_loadMore);
super.onInit();
}
_getData() async {}
_loadMore() async {}
#override
void onClose() {
scrollController.removeListener(_loadMore);
super.onClose();
}
}
---I noticed Get.offNamed at first it reads the Controller of new page (in my case it's the same page)
[GETX] Instance "PostsController" has been created
[GETX] Instance "PostsController" has been initialized
Then deletes the controller of old page (in my case it's the same page)
[GETX] "PostsController" onDelete() called
[GETX] "PostsController" deleted from memory
Because of working in this order, the scrollController is lost. If it works the other way around the scrollController will be reinitialized.
I don't know how to go to the same page after deleting the controller (Firstly) and reinitializing it (secondly), or not calling onClose() when going to the same page as replacment
You can try initializing your scroll controller in the initstate like this:
class PostsController extends GetxController with StateMixin<Posts> {
late final ScrollController scrollController;
#override
void onInit() {
_getData();
scrollController = ScrollController()..addListener(_loadMore);
super.onInit();
}
_getData() async {}
_loadMore() async {}
#override
void onClose() {
scrollController.removeListener(_loadMore);
super.onClose();
}
}

Flutter GetX call fetch data only once in the build methode

I have a method called getData() which used to load data from API,
and i am displaying data in a separate screen, I have one issue which whenever I navigate to this page it rebuild the whole screen and call the API again and again.
PS: I'm using getX Obx to control the UI
Question: how to call the function only when new data has added
class CategoryPageBinding extends Bindings {
#override
void dependencies() {
Get.put(CategoryPageController(), permanent: true);
}
}
class CategoryPageController extends GetxController {
#override
void onInit() {
super.onInit();
getAllCategories();
}
}
You can call the method in Controller using getX.
#override
void onInit() {
super.onInit();
getData();
}

GetxController onClose not called

I have a getx controllers A which has a property of another controller B. But when I delete the controller A, the onClose() of A is called while the onClose of B isn't.
// Controller A
#override
void onClose() {
print('close A');
B.dispose();
super.onClose();
}
//Controller B
#override
void onClose() {
print('close B');
animationController.dispose();
super.onClose();
}
until i add this line
#override
void onClose() {
B.onClose();
B.dispose();
super.onClose();
}
I'm newly interested in Getx, thanks for viewing this question:)
Is your controller B is being used by any other page/controller? If so, it's the expected behavior.
Also, you shouldn't call lifecycle methods (onInit, onClose) manually.

Flutter custom navigation highlight selected page

I'm currently building a custom bottom bar for quick navigation.
I used the Navigation Service described in this article
Now I want to add highlighting based on which page the user has selected.
I tried to add RouteAware to my BottomNav widget to update the menu when the routing changed but I'm not receiving any events only when starting my app.
class _BottomNavState extends State<BottomNav> with RouteAware {
String _selectedRoute;
AppRouteObserver _routeObserver;
#override
void initState() {
super.initState();
_routeObserver = AppRouteObserver();
}
#override
void didChangeDependencies() {
super.didChangeDependencies();
_routeObserver.subscribe(this, ModalRoute.of(context));
}
#override
void dispose() {
_routeObserver.unsubscribe(this);
super.dispose();
}
#override
void didPush() {
print('didPush');
}
The Route observer is a simple class:
class AppRouteObserver extends RouteObserver<PageRoute> {
factory AppRouteObserver() => _instance;
AppRouteObserver._private();
static final AppRouteObserver _instance = AppRouteObserver._private();
}
I'm guessing that it has to with me not using the Navigator.pushNamed but the direct implementation of the Navigation Service.
class NavigationService {
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
Future<dynamic> navigateTo(String routeName, {var content}) {
return navigatorKey.currentState.pushNamed(routeName, arguments: content);
}
bool goBack() {
return navigatorKey.currentState.pop();
}
}
The reason I created the NavigationService is because I want to show a consistent layout on every page (menubar / bottom bar / background).
Is there a better way to solve this problem?
I fixed the issue by extending the NavigationService with a ChangeNotifier.
Now when the user clicks the button I call a setSelected function and notify the menu items to redraw them self's.
setSelected(String newRoute) {
_showLeading = !checkIsHome(newRoute);
this._currentRoute = newRoute;
notifyListeners();
}