Search code examples
flutterdartflutter-layoutflutter-state

list view not refreshing in flutter


I am using two bottomnavigationbar item where two tabs for alltodos and completedtodos

here as a demo purpose I have placed a refresh button on AppBar to load data and used setState to rebuild but it does not rebuild list view , therefor to see data, I have to click on bottom tab..

I want auto refresh on clicking refresh button

here is my code...


class _HomePageState extends State<HomePage> {
  int selectedindex=0;

  final tabs=[
    ViewList(iscompleted: false,),
    ViewList(iscompleted:true),
  ];



  @override
  Widget build(BuildContext context) {
    print('Main Build Method');

    return Scaffold(
        appBar: AppBar(title: Text('Todo App'),
        actions: [IconButton(onPressed: (){
          alltodos.clear();
           alltodos.add(Todo(title: 'first',iscompleted: false));
          alltodos.add(Todo(title: 'Second',iscompleted: false));
          alltodos.add(Todo(title: 'Third',iscompleted: false));
          alltodos.add(Todo(title: 'Fourth',iscompleted: true));
          alltodos.add(Todo(title: 'Fifith',iscompleted: false));
          alltodos.add(Todo(title: 'Sixth',iscompleted: false));
          alltodos.add(Todo(title: 'Seven',iscompleted: true));
          setState(() {
          });
        }, icon: Icon(Icons.refresh))],),
        body:tabs[selectedindex],
        bottomNavigationBar: BottomNavigationBar(
          backgroundColor: Colors.white,
          unselectedItemColor: Colors.grey,
          selectedItemColor: Colors.blue,
          currentIndex: selectedindex,
          onTap: (index){
            selectedindex=index;
            setState(() {
            });
          },
          items: [
            BottomNavigationBarItem(icon: Icon(Icons.fact_check_outlined),
                label: 'Todos'),
            BottomNavigationBarItem(
                label: 'Completed',
                icon: Icon(Icons.done))
          ],
        ),


    );
  }

}


class ViewList extends StatelessWidget {
  final bool iscompleted;

  ViewList({required this.iscompleted});


  @override
  Widget build(BuildContext context) {
    List<Todo> mylist=alltodos.where((element) {
      return element.iscompleted==iscompleted;
    }).toList();

   return ListView.builder(
        itemCount: mylist.length,
        itemBuilder: (context,index){
        final todo=mylist[index];
        return ListTile(
          leading: CircleAvatar(),
          title: Text(todo.title),
          subtitle: Text(todo.iscompleted.toString()),

        );

        });
  }
}

todo model class

class Todo
{

  String title;
  bool iscompleted;

  Todo({required this.title,this.iscompleted=false});



}

List<Todo> alltodos=[
 
];

Solution

  • Here you are creating variable, therefore it is breaking context update relation.

      final tabs=[
        ViewList(iscompleted: false,),
        ViewList(iscompleted:true),
      ];
    

    You can reassign data by removing the final and this will update

    onPressed: () {
      ..
      tabs = [
        ViewList(
          iscompleted: false,
        ),
        ViewList(iscompleted: true),
      ];
      setState(() {});
    },
    

    Better, When you need something that will rebuild, use helper method or widget

    tabs() => [
            ViewList(
              iscompleted: false,
            ),
            ViewList(iscompleted: true),
          ];
    

    And use

    body: tabs()[selectedindex],
    

    Also it will be a good startup using state-management like provider/riverpod/bloc