Flutter GetX controller not calling method when revisit the app screen
Asked Answered
C

3

5

I am new to the Flutter GetX package and facing problem when using the flutter GetX package. I have several app screens where one screen for listing all the products from the database.

In my product controller, I am fetching all the data from the database and showing with listview like as given code below and It's working fine.

Problem: When I'm inserting a new record from another controller and come back to the product list controller it'll not showing newly added data. Actually this time onInit method won't fire.

Controller code

class ProductIndexCtrl extends GetxController {
    
    var products = [].obs;

    @override
    void onInit() {
     super.onInit();
     getAll();
    }

    void getAll() {
      Product.getAll().then((jsonList) {
        products.value = Product.fromJsonList(jsonList);
      });
    }
}



class ProductCreateCtrl extends GetxController {
    
     void saveData(Product product) {
        ...
        ...

        //after successful insert
        Get.toNamed('productIndex');

     }

}

Product index screen

final ctrl = Get.put(ProductIndexCtrl());

GetX<ProductIndexCtrl>(builder: (controller) {
    return _listview(controller.products);
}

Widget _listview(data) {
    ...
    ...
}
Ceremonial answered 22/6, 2021 at 14:26 Comment(0)
D
7

As the GetX dependency manager controls the lifecycle of dependencies, you should not manually call them. It's GetX's responsibility when to call them.

Therefore you need to manually call getAll() method of your ProductIndexCtrl controller inside the saveData() method of your ProductCreateCtrl like:

saveData(Product product){
  .... 
  ....
  final indexCtrl= Get.find<ProductIndexCtrl>();
  indexCtrl.getAll();

}
Doom answered 22/6, 2021 at 16:14 Comment(1)
Damn, wasted a couple of hours but finally found the answer. Thanks, mate.Selfseeker
C
1

By returning to that page, you can return the new information locally to the previous page

> Controller code

class ProductIndexCtrl extends GetxController {

var products = [].obs;

@override
void onInit() {
 super.onInit();
 getAll();
}

void getAll() {
  Product.getAll().then((jsonList) {
    products.value = Product.fromJsonList(jsonList);
  });
}

}

> Product index screen

class ProductCreateCtrl extends GetxController {

 void saveData(Product product) {
    ...
    ...

    //after successful insert
    Get.back(result: product);

 }

}

and get Data when back

Get.toName('ProductCreateCtrl').then(result){
 products.add(result); 

}

Caldwell answered 11/2, 2022 at 15:0 Comment(0)
I
1

I tried a similar thing with one single controller. The code snippet is given below.

First, create the ProductView. Since this is the entry point of the application, So you will create a GetX controller inside of this.

/// THIS IS PARENT VIEW SO WE WILL CREATE GETX CONTROLLER HERE
class ProductView extends StatelessWidget {
  const ProductView({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final controller = Get.put(ProductController());
    return Scaffold(
      appBar: AppBar(
        title: const Text('Products'),
      ),
      body: Obx(() {
        return controller.myProductList.isEmpty
            ? showNoProductView()
            : ListView.builder(
              itemCount: controller.myProductList.length,
                itemBuilder: (context, index) {
                  return YourListItemView(controller.myProductList[index]);
                },
              );
      }),
    );
  }
}

The view AddProductView is responsible for adding new products to the DB. We can assume that there is a FloatingActionButton present in ProductView and onClick on that button, we will open this AddProductView.

/// THIS IS CHILD VIEW SO WE WILL FIND THE PRODUCT CONTROLLER HERE
class AddProductView extends StatelessWidget {
  const AddProductView({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final controller = Get.find<ProductController>();
    return Scaffold(
      appBar: AppBar(
        title: const Text('Add Product'),
      ),
      body: Column(
        children: [
          // ADD YOUR OTHER WIDGETS TO GET PRODUCT INFO
          TextButton(
            child: const Text('Click to Add'),
            onPressed: () {
              var productName = nameTextEditingController.text;
              var productQuantity = qtyTextEditingController.text;

              var product = YourProductObject(productName, productQuantity);
              controller.addProduct(product: product);
            },
          )
        ],
      ),
    );
  }
}

Finally, the controller will look like this.

import 'package:get/get.dart';

class ProductController extends GetxController {
  // this will be your custom product list object
  var myProductList = <YourProductObject>[].obs;

  var dbInstance = YourDbInstance();

  @override
  void onReady() async {
    super.onReady();

    // perform database operation
    await fetchDataFromDb();
  }

  Future<void> fetchDataFromDb() async {
    // assuming that data is coming as List<YourProductListObject>
    // always use try catch in db operation. for demo purpose I am skipping that.
    var productListFromDb = await dbInstance.getYourProductListObjectList();

    myProductList.assignAll(productListFromDb);
  }

  Future<void> addProduct({required YourProductObject product}) async {
    // assuming that there is a function that returns true if a product is added to db
    var isAdded = await dbInstance.addProduct(product);

    if (isAdded) {
      myProductList.add(product);
    }
  }
}

Since myProductList is a RxList so getx will observe it and will update the UI accordingly. You must add Obx((){}) in view.

Internal answered 30/7, 2022 at 20:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.