Home > Software engineering >  Flutter GetX Re-Initialise GetX Controller Reset GetX Controller, Reset GetX Controller Values
Flutter GetX Re-Initialise GetX Controller Reset GetX Controller, Reset GetX Controller Values

Time:04-22

I am learning Flutter GetX to my own and stuck on a point. Actually I want to know why onInit method of GetX Controlled is not calling whenever I revisit that page/dialog again.

Suppose that I have dialog with a simple TextField, a Listview the TextField is used for searching the listview. When the User enters any filter key inside the text field, the listview will be filtered.

Here is the Sample Dialog:

import 'package:flutter/material.dart';
import 'package:flutter_base_sample/util/apptheme/colors/app_colors.dart';
import 'package:flutter_base_sample/util/apptheme/styles/text_styles_util.dart';
import 'package:flutter_base_sample/util/commons/app_util.dart';
import 'package:flutter_base_sample/util/widgets/alert/controllers/country_finder_alert_controller.dart';
import 'package:flutter_base_sample/util/widgets/marquee/marquee_widget.dart';
import 'package:flutter_base_sample/util/widgets/textfields/app_text_field.dart';
import 'package:get/get.dart';

class SampleDialogWidget extends StatelessWidget {
  final CountryFinderAlertController controller = Get.put(CountryFinderAlertController(),permanent: true);

  @override
  Widget build(BuildContext context) {
    return Dialog(
      insetPadding: AppUtil.dialogPadding(context),
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(20),
      ),
      elevation: 0.0,
      backgroundColor: Colors.white,
      child: dialogContent(context),
    );
  }

  Widget dialogContent(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      mainAxisAlignment: MainAxisAlignment.start,
      mainAxisSize: MainAxisSize.max,
      children: [
        Text(
          "Hello Heading",
          style: TextStyleUtil.quickSandBold(context, fontSize: 16, color: Colors.blue),
          textAlign: TextAlign.center,
        ),
        SizedBox(
          height: 20,
        ),
        Expanded(
          child: SingleChildScrollView(
            child: Container(
              height: AppUtil.deviceHeight(context),
              padding: EdgeInsetsDirectional.all(20),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                crossAxisAlignment: CrossAxisAlignment.stretch,
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text("Hello Text1"),
                  SizedBox(
                    height: 10,
                  ),
                  getSearchField(context),
                  SizedBox(
                    height: 5,
                  ),
                  Expanded(
                    child: Obx(()=> getFavoritesListView(context)),
                  )
                ],
              ),
            ),
          ),
        ),
        SizedBox(
          height: 20,
        ),
        Container(
          margin: EdgeInsetsDirectional.only(start: 20,end: 20),
          child: ElevatedButton(
            onPressed: () {},
            style: ButtonStyle(
              overlayColor: MaterialStateProperty.all<Color>(Colors.red),
              // splashFactory: NoSplash.splashFactory,
              elevation: MaterialStateProperty.all(0.5),
              backgroundColor: MaterialStateProperty.resolveWith<Color>(
                (Set<MaterialState> states) {
                  if (states.contains(MaterialState.pressed)) {
                    return AppColors.instance.black.withOpacity(0.1);
                  } else {
                    return Colors.blue; // Use the component's default.
                  }
                },
              ),
            ),
            child: Text(
              "Hello Footer",
              style: TextStyleUtil.quickSandBold(context, fontSize: 16, color: Colors.yellow),
              textAlign: TextAlign.center,
            ),
          ),
        )
      ],
    );
  }

  Widget getFavoritesListView(BuildContext context) {
    if (controller.favoritesList.length > 0) {
      return ListView.separated(
        shrinkWrap: true,
        itemCount: controller.favoritesList.length,
        itemBuilder: (BuildContext context, int index) => _topupFavoriteContent(context, index),
        separatorBuilder: (context, index) {
          return Divider(
            indent: 15,
            endIndent: 15,
          );
        },
      );
    } else {
      return Center(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          mainAxisAlignment: MainAxisAlignment.center,
          mainAxisSize: MainAxisSize.min,
          children: [
            Text(
              "No Data Found!",
              textAlign: TextAlign.center,
            ),
            SizedBox(
              height: 20,
            ),
          ],
        ),
      );
    }
  }

  Widget _topupFavoriteContent(BuildContext context, int index) {
    final item = controller.favoritesList[index];
    return InkWell(
        onTap: () {
          Get.back(result:item);
          // AppUtil.pop(context: context, valueToReturn: item);
        },
        child: getChildItems(context, index));
  }

  Widget getChildItems(BuildContext context, int index) {
    return Directionality(textDirection: TextDirection.ltr, child: getContactNumberAndNameHolder(context, index));
  }

  Widget getContactNumberAndNameHolder(BuildContext context, int index) {
    final item = controller.favoritesList[index];
    return Container(
      padding: EdgeInsetsDirectional.only(start: 20, end: 20, top: 20, bottom: 10),
      child: Column(
        children: [
          Row(
            // crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Flexible(
                child: Align(
                  alignment: AlignmentDirectional.centerStart,
                  child: Text(
                    item.name ?? "",
                    style: TextStyleUtil.quickSandBold(context, fontSize: 15, color: AppColors.instance.black),
                  ),
                ),
              ),
              SizedBox(
                width: 5,
              ),
              Container(),
              Align(
                alignment: AlignmentDirectional.centerEnd,
                child: MarqueeWidget(
                  child: Text(
                    item.dialCode ?? "",
                    style: TextStyleUtil.quickSandBold(context, fontSize: 15, color: Colors.blue),
                  ),
                ),
              ),
            ],
          )
        ],
      ),
    );
  }

  Widget getSearchField(
    BuildContext context,
  ) {
    return Container(
        margin: EdgeInsetsDirectional.only(start: 20, end: 20, top: 20),
        child: Row(
          children: [
            Expanded(
              child: AppTextField(
                onChanged: (String text) {
                  controller.performSearchOnForFavoriteContact(text);
                },
                isPasswordField: false,
                keyboardType: TextInputType.text,
                suffixIconClickCallBack: () {},
              ),
            )
          ],
        ));
  }
}

and here is the GetX Controller:

class CountryFinderAlertController extends GetxController {
  TextEditingController countrySearchFieldEditController = TextEditingController();
  RxList<CountryHelperModel> favoritesList;
  RxList<CountryHelperModel> originalList;

  @override
  void onInit() {
    super.onInit();
    debugPrint("Hello222");
    favoritesList = <CountryHelperModel>[].obs;
    originalList = <CountryHelperModel>[].obs;
  }

  @override
  void onReady() {
    super.onReady();
    debugPrint("Hello111");
    originalList.addAll(JSONHelperUtil.getCountries());
    addAllCountries();
  }

  @override
  void dispose() {
    super.dispose();
    countrySearchFieldEditController.dispose();
  }

  @override
  void onClose() {
    super.onClose();
  }

  void performSearchOnForFavoriteContact(String filterKey) {
    if (filterKey != null && filterKey.isNotEmpty) {
      List<CountryHelperModel> filteredFavoritesList = [];

      debugPrint("filterKey"   filterKey);
      originalList.forEach((element) {
        if (element.name.toLowerCase().contains(filterKey.toLowerCase()) ||
            element.countryCode.toLowerCase().contains(filterKey.toLowerCase()) ||
            element.dialCode.toLowerCase().contains(filterKey.toLowerCase())) {
          filteredFavoritesList.add(element);
        }
      });

      if (filteredFavoritesList.isNotEmpty) {
        favoritesList.clear();
        favoritesList.addAll(filteredFavoritesList);
      } else {
        favoritesList.clear();
      }
    } else {
      //reset the list
      addAllCountries();
    }
  }

  void addAllCountries() {
    favoritesList.clear();
    favoritesList.addAll(originalList);
  }
}

So what I want is to load fresh data each time when I open this dialog. For now, if user will search for any country and close the dialog and then if reopen it the user will see the older search results.

In simple means how can GetX Controller be Reset/Destroyed or reinitialised !

Thanks in advance

CodePudding user response:

I believe it's because of ,permanent: true
Try leaving that out.

CodePudding user response:

So the answer to this question from me is that the Flutter pub GetX do provide a way to delete any initialised controller. Let's suppose that we only have a controller that needs to call an API in its onInit() method, every time the user will land on that specific view controller suppose!

So the solution to this problem is to just call:

Get.delete<YourControllerName>();

The thing that when it should get called is important. For me the clean way to do it, when I goto a new page I register a value to return/result callback as:

Get.to(()=>YourWidgetView());

to

Get.to(()=>YourWidgetView()).then((value) => Get.delete<YourControllerName>());

So whenever the user will leave your Widget View will delete the respected controller. In this way when the user will come again to the same widget view, the controller will re-initialised and all the controller values will be reset.

If anyone does have any better solution can share with the dev community. Thanks

CodePudding user response:

Disposing your resources always come after disposing super resources. So change the following

@override
  void dispose() {
    super.dispose();
    countrySearchFieldEditController.dispose();
  }

with

@override
  void dispose() {
    countrySearchFieldEditController.dispose();
    super.dispose();
  }

If it still not works, please attach the binding file code as well.

CodePudding user response:

Controller won't get disposed:

class SampleDialogWidget extends StatelessWidget {
  final CountryFinderAlertController controller = Get.put(CountryFinderAlertController(),permanent: true);

  @override
  Widget build(BuildContext context) {
    return Dialog(

Instantiation & registration (Get.put(...)) should not be done as a field.

Otherwise, the registration of controller is attached to LandingScreen, not MainScreen. And Controller will only get disposed when LandingScreen is disposed. Since that's the home Widget in the code above, disposal only happens upon app exit.

Fix: Move Get.put to the build() method.

class SampleDialogWidget extends StatelessWidget {
      
      @override
      Widget build(BuildContext context) {
      final CountryFinderAlertController controller = Get.put(CountryFinderAlertController());
        return Dialog(
  • Related