skip to Main Content

I am facing a problem in my current project for rebuilding future builder whenever data is added or updated..

after adding a number into numbers, future builder should be rebuild to show all updated numbers..

i have wrapped Future builder inside Obx but its not rebuilding as it does not contain any obs variable inside it…

So how to refresh it..on adding or deleting number

Widget build(BuildContext context) {
    final controller = Get.put(DataController());
    return Scaffold(
      body: Column(
        children: [
          Expanded(
            child:  Obx(
                ()=>FutureBuilder(
               future: controller.fetchData(),
                    builder: (context, snapshot) {
                      const loader = Center(child: CircularProgressIndicator());

                      if (snapshot.connectionState == ConnectionState.waiting)
                        return loader;

                      if (!snapshot.hasData ||
                          snapshot.data == null ||
                          snapshot.data!.isEmpty)
                        return Center(
                          child: Text('No data found'),
                        );

                      if (snapshot.hasError) {
                        return const Center(
                          child: Text('Error found'),
                        );
                      }

                      final allData = snapshot.data!;

                      return ListView.builder(
                          shrinkWrap: true,
                          itemCount: allData.length,
                          itemBuilder: (context, index) {
                            final data = allData[index];
                            return ListTile(
                              title: Text(data.toString()),
                            );
                          });
                    })
            ),
          ),
          SizedBox(
              height: 100,
              width: double.infinity,
              child: ElevatedButton(onPressed: (){
                final num=Random().nextInt(1000);
                numbers.add(num);
              },child: Text('Add Number'),))
        ],
      ),

    );
  }

data controller


class DataController extends GetxController {
  RxBool isLoading = false.obs;
 

  Future<List<int>> fetchData() async {
    try {
      isLoading.value = true;
      final data = numbers;//numbers is a list[int] stored in different file
      return data;
    } catch (e) {
      print('Something wrong');
      return [];
    } finally {
      isLoading.value = false;
    }
  }
}

for data source
i have just created a list of int in a sepearate file

List<int> numbers=[1,2,3];

2

Answers


  1. To ensure that the FutureBuilder updates when data is added or deleted, you can make use of a StatefulWidget along with a setState call.

    class YourWidget extends StatefulWidget {
    @override
     _YourWidgetState createState() => _YourWidgetState();
    }
    
    class _YourWidgetState extends State<YourWidget> {
         final controller = Get.put(DataController());
    
     @override
     Widget build(BuildContext context) {
      return Scaffold(
      body: Column(
        children: [
          Expanded(
            child: Obx(
              () => FutureBuilder(
                future: controller.fetchData(),
                builder: (context, snapshot) {
                  // Your existing code here
                },
              ),
            ),
          ),
          SizedBox(
            height: 100,
            width: double.infinity,
            child: ElevatedButton(
              onPressed: () {
                final num = Random().nextInt(1000);
                numbers.add(num);
                setState(() {}); // Trigger rebuild
              },
              child: Text('Add Number'),
            ),
          ),
        ],),);
       }
     }
    

    by calling "setState" after adding a number, you will trigger a rebuild of that widget, which wil subsequently trigger the FutureBuilder to evaluate again its future, resultin in fetching updated data. your UI will reflect the changes made to the numbers list.

    Login or Signup to reply.
  2. If you are using GetX to manage your state, you should know the 3 options to do that (you can see it here).

    Here is how you can change your code to make a dynamic list using Get:

    • You have a loading state in your controller, so you can use that to show a loading widget and remove the FutureBuilder (ps: this is a option, you can use both either, you can learn more about FutureBuilder here).
    • You want to watch a list change, so we can make a observableList inside your controller and watch the changes (you can see about reactive state in the getx oficial documentation).
    • Now we need to create a function that will update the list, so we can call the function in the add number button.

    Now this should work.

    View:

    Widget build(BuildContext context) {
    final controller = Get.put(DataController());
    return Scaffold(
      body: SafeArea(
        child: Column(
          children: [
            Expanded(
              child: Obx(
                () => controller.isLoading.value
                    ? const Center(child: CircularProgressIndicator())
                    : ListView.builder(
                        shrinkWrap: true,
                        itemCount: controller.numbers.length,
                        itemBuilder: (context, index) {
                          final data = controller.numbers[index];
                          return ListTile(
                            title: Text(data.toString()),
                          );
                        }),
              ),
            ),
            SizedBox(
                height: 100,
                width: double.infinity,
                child: ElevatedButton(
                  onPressed: () {
                    final num = Random().nextInt(1000);
                    controller.addNumber(num);
                  },
                  child: const Text('Add Number'),
                ))
          ],
        ),
      ),
    );
    

    }

    Controller:

    class DataController extends GetxController {
      RxBool isLoading = true.obs;
      RxList<int> numbers = <int>[].obs;
    
      @override
      onInit() {
        super.onInit();
        fetchData();
      }
    
      Future<void> fetchData() async {
        await Future.delayed(const Duration(seconds: 2));
        try {
          isLoading.value = true;
          numbers.value = [1, 2, 3];
        } catch (e) {
          print('Something wrong');
        } finally {
          isLoading.value = false;
        }
      }
    
      void addNumber(int number) {
        numbers.add(number);
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search