Muhammad Qazmouz
Muhammad Qazmouz

Reputation: 431

Flutter: Getx navigation return null

I use GetX package since a while, but sometimes I suffer from some mistakes..

Now I have a bottomNavigationBar which has 5 pages to navigate between (Offers - Categories - Cart - Favorite - Account).

My problem is:

When I go from index 0 to index 2 (for an example), it goes normally, but when I want to get back to index 0, here the app crashes and give me this error:

Null check operator used on a null value

The same way I was using with another project, but there I was using TabBar, I used it normally without this mistake, but here in the bottom navigation bar it happens.

Actually I don't believe that the error because of the widget kind, but really want to solve it.

Note :

I created a HomePageController which I defined all of the bottomNavigationBar operations, like changing the index, and the list of pages, ..etc

And for each page it has its controller, even when I get back to the page which uses HomePageController it crashes!!!

This is a simple of my code:

class HomePageController extends GetxController {
  static HomePageController instance = HomePageController();

  late TextEditingController categoriesSearchController;

  @override
  void onInit() {
    super.onInit();
    categoriesSearchController = TextEditingController();
  }

  int bottomNavIndex = 0;

  changeBottomIndex(int index) {
    bottomNavIndex = index;
    update();
  }


  List<Widget> bottomScreens = const [
    Offers(),
    Categories(),
    Cart(),
    Favorite(),
    Account(),
  ];

  List<ItemModel> meatsList = [
    ItemModel(
      title: 'Thigh',
      image: 'assets/images/home_page/pin_thigh.png',
      description: '1 Kg',
      price: 1.72,
    ),
    ItemModel(
      title: 'Breast',
      image: 'assets/images/home_page/breasts2.jpg',
      description: '1 Kg',
      price: 1.65,
    ),
    ItemModel(
      title: 'lamb',
      image: 'assets/images/home_page/lamb.jpeg',
      description: '1 Kg',
      price: 6.55,
    ),
  ];
}
class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return GetBuilder<HomePageController>(
      builder: (controller) => controller != null
          ? SafeArea(
              child: Scaffold(
                backgroundColor: AppColors.whiteColor,
                bottomNavigationBar: BottomNavigationBar(
                  items: controller.changingBottom(),
                  currentIndex: controller.bottomNavIndex,
                  type: BottomNavigationBarType.fixed,
                  selectedItemColor: AppColors.onBoardingButton,
                  onTap: (index) {
                    controller.changeBottomIndex(index);
                  },
                ),
                body: controller.bottomScreens[controller.bottomNavIndex],
              ),
            )
          : const Center(
              child: CircularProgressIndicator(),
            ),
    );
  }
}

Update:

I forgot to mention that I use GetX Binding class to initialize all controllers when it's needed, like this way:

class Binding extends Bindings {
  @override
  void dependencies() {
    Get.put(() => DatabaseController());
    Get.lazyPut(() => AuthController());
    Get.lazyPut(() => HomePageController());
    Get.lazyPut(() => ProductsController());
    Get.lazyPut(() => CartController());
  }
}

So there is no need to initialize each controller in each page.

Upvotes: 0

Views: 671

Answers (2)

Muhammad Qazmouz
Muhammad Qazmouz

Reputation: 431

Finally I got solution.. I had to use Get.find<xController>() in each UI page I use any controller class in it.

Widget build(BuildContext context) {
    return GetBuilder<CartController>(
      init: Get.find<CartController>(),
      builder: (controller) => Scaffold(),

And after testing, it works good.

Upvotes: 0

Cavin Macwan
Cavin Macwan

Reputation: 1238

In your Homepage, add init method and autoRemove in GetBuilder like this:

class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return GetBuilder<HomePageController>(
      init:HomePageController(),
      autoRemove:false,
      builder: (controller) => controller != null
          ? SafeArea(
              child: Scaffold(
                backgroundColor: AppColors.whiteColor,
                bottomNavigationBar: BottomNavigationBar(
                  items: controller.changingBottom(),
                  currentIndex: controller.bottomNavIndex,
                  type: BottomNavigationBarType.fixed,
                  selectedItemColor: AppColors.onBoardingButton,
                  onTap: (index) {
                    controller.changeBottomIndex(index);
                  },
                ),
                body: controller.bottomScreens[controller.bottomNavIndex],
              ),
            )
          : const Center(
              child: CircularProgressIndicator(),
            ),
    );
  }
}

By using init, it will rebuild your controller if it is disposed. And, by using autoRemove to false, it won't dispose the controller every single time.

Upvotes: 1

Related Questions