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
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 controllersPage1Controller(),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 callGet.to(Page2())
i make sure that thePage2Controller()
is already deleted so i useGet.delete<Page2Controller>();
and to test this you can see the logePage2Controller() onInit()
.so the full solution code is like that:
Page1Controller Navigation:
and Page2Controller :
you will find out that with this approach the Page2Controller will get Re-Initialized every time you go to Page2
@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.