skip to Main Content

I’m Using GetX As A State Management Tool and it was very helpful,
but I got a bug when navigating to a page and going back the page controller doesn’t get disposed and the onClose() method doesn’t get called so I can’t dispose the controller manually using Get.delete<Controller>().
and I checked answers here pointing out to initialize the controller in the build() method and it also didn’t work.

I’m using GetX ^4.6.5

Navigating with Named Navigation i.e Get.toNamed('/page1 )

UPDATE

code snippet
the Page

class UnitsList extends StatelessWidget {

  const UnitsList({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    const horizontalPadding = EdgeInsets.symmetric(horizontal: 10);
    final UnitsListController controller = Get.put(UnitsListController());

    return Scaffold(
      appBar: AppBar(
        title: Text('Units List'),
        centerTitle: true,
      ),
      body: Padding(
        padding: horizontalPadding,
        child:GetX<UnitsListController>(
          builder: (_)=>controller.isBusy.value
              ?const AppCircularIndicator()
              : SingleChildScrollView(
              child: Column(
                children: [
                  GetBuilder<UnitsListController>(
                    builder:(_)=> ListView.builder(
                      shrinkWrap: true,
                      physics: const NeverScrollableScrollPhysics(),
                      itemCount: controller.unitsList.length,
                      itemBuilder: (context, index) {
                        var item = controller.unitsList[index];                    
                        return GestureDetector(
                          onTap: () {
                            controller.selectedUnit = item;
                            print('${controller.selectedUnit!.rent}');
                            controller.onUnitTap();
                          },
                          child:  AppUnitCard(
                           //...
                          ),
                        );
                      },
                    ),
                  ),
                ],
              )
          ),
        )

      ),
    );
  }
}

And the Controller

class UnitsListController extends GetxController {
  final _className = 'Units List Controller';

  List<Unit> unitsList = [];

  String? _requestType;

  RxBool isBusy = false.obs;
  Unit? selectedUnit;

  @override
  void onInit() async {
    log('onInit', name: _className);

    isBusy.value = true;

    //Some APIs Calls and handling data
    super.onInit();
  }

  @override
  void onReady() {
    isBusy.value = false;
    log('onReady', name: _className);
    super.onReady();
  }

  @override
  void onClose() {
    log('onClose', name: _className);
    super.onClose();
  }

  void onUnitTap() {
    log('_requestType : $_requestType', name: _className);
    if(selectedUnit == null ||_requestType==null){
      return;
    }
    

      var selectedUnitData = {NavigationParams.unit: selectedUnit!.toJson()};
    
      if (_requestType == NotificationsStrings.evacuation) {
        Get.toNamed(AppRoutes.evacuationRequestPage,
            arguments: selectedUnitData);
      } else if (_requestType == NotificationsStrings.maintenance) {
        Get.toNamed(AppRoutes.maintenanceRequestPage,
            arguments: selectedUnitData);
      } else if (_requestType == NotificationsStrings.renting) {
        Get.toNamed(AppRoutes.paymentServicesList, arguments: selectedUnitData);
      } else if (_requestType == NavigationParams.searchUnitTapRequest) {
        Get.toNamed(AppRoutes.unitDetailsPage,
            arguments: selectedUnitData,
            parameters: {
              NavigationParams.unitDetailsKey: NavigationParams.unitDetailsRent
            });
      }
      else if (_requestType == NavigationParams.customerViewUnitTapRequest) {
        Get.toNamed(AppRoutes.unitDetailsPage,
            arguments: selectedUnitData,
            );
      }
      else if (_requestType == NavigationParams.ownerInvitingSpUnitTapRequest) {
        Get.toNamed(AppRoutes.servicesProvidersList,
            arguments: selectedUnitData);
      }
      else if (_requestType == NavigationParams.ownerViewUnitTapRequest ||
          _requestType == NavigationParams.ownerViewEmptyUnitTapRequest ||
          _requestType == NavigationParams.ownerViewOccupiedUnitTapRequest) {
        Get.toNamed(AppRoutes.unitDetailsPage,
            arguments: selectedUnitData,
            parameters: {
              NavigationParams.unitDetailsKey: NavigationParams.unitDetailsEdit
            });
      }  
  }  
}

so please any help would be appreciated

2

Answers


  1. Chosen as BEST ANSWER

    So I've solved my problem with a work around approach, so don't judge me if that's not a best practice or a poor solution.

    lets consider that i have a two pages Page1(),Page2() and their controllers Page1Controller(),Page2Controller(). and i wanted to go back and forth and when i revisit Page2() i wanted it's controller to be re-Initialized.

    so what i did simply is when i'm at Page1() and before i call Get.to(Page2()) i make sure that the Page2Controller() is already deleted so i use Get.delete<Page2Controller>(); and to test this you can see the loge Page2Controller() onInit().

    so the full solution code is like that:

    Page1Controller Navigation:

    Get.delete<Page2Controller>();
     Get.to(Page2());
    

    and Page2Controller :

    import 'dart:developer';
    
    class Page2Controller extends GetxController {
    final _className='Page 2 Controller';
    
     @override
      void onInit() async{
    log('onInit',name:_className);
    }
    }
    

    you will find out that with this approach the Page2Controller will get Re-Initialized every time you go to Page2


  2. @AbanoubRefaat the Controller is bond to the named route, it will get disposed when the route popped.

    In your case, you are pushing the page on top of another page. The controller won’t be disposed because page A is still there.
    When you pop pageB, Page2Controller will be disposed.
    If you replace pageA with pageB by calling Get.offNamed, PageAController will be disposed.

    // Going to a page
    Get.toNamed(AppLinks.DASHBOARD);
    // Move back one page only
    Get.offNamed(AppLinks.LOGIN);
    
    // Going back all route/pages until LOGIN page you can even pass a predicate/ condition to pop until that condition passes
    Get.offAllNamed(AppLinks.LOGIN);
    
    
    // Pop the current route and to the defined route.
    Get.offAllAndToNamed(AppLinks.ORDERS);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search