Flutter Provider doesn't trigger rebuild when model is changed with context and watch

Viewed 544

I am using a FutureProvider with flutter. Here's my add_match_screen.dart file and here I am initiating the provider to use it inside other widgets.


    class _AddMatchScreenState extends State<AddMatchScreen> {
      late Future<List<Team>> _teamsFuture;
    
      @override
      void initState() {
        super.initState();
        _teamsFuture = Team.getAllTeams();
      }
    
      @override
      Widget build(BuildContext context) {
        return Layout(
          appBarTitle: 'Add New Match',
          body: FutureProvider<List<Team>>(
            initialData: const [],
            create: (context) => _teamsFuture,
            child: MatchForm(),
          ),
        );
      }
    }

And I am listening for changes inside match_form.dart file. Something like this.


    @override
      Widget build(BuildContext context) {
        final _teams = context.watch<List<Team>>();
        
        // print statement here
        print(_items); 

        return Container(
            ....something
        );
    }

If I do a print statement here, I can see it printing [] and [instance of Team] a moment later, which is expected, right? But read the following code carefully.


    @override
      Widget build(BuildContext context) {
        final teams = context.watch<List<Team>>();
        print(teams);
        return teams.isEmpty
            ? const Loader()
            : Container(
                // something
              );
        }

Here I am trying to use teams from provider. If teams property is empty then I am showing a loader but my print statement runs but my code doesn't rebuild and it just shows the loader forever. So what am I doing wrong here?

The layout.dart file


    class Layout extends StatelessWidget {
      final Widget body;
      final String appBarTitle;
      final List<Widget> actions;
    
      const Layout({
        Key? key,
        required this.appBarTitle,
        required this.body,
        this.actions = const [],
      }) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          resizeToAvoidBottomInset: false,
          drawer: const TheDrawer(),
          appBar: AppBar(
            title: Text(appBarTitle),
            actions: actions,
          ),
          body: body,
        );
      }
    }

1 Answers

My guess is it doesn't see a change in the widget tree and it doesn't know that it needs to rebuild.

I would change your match_form.dart into a stateful widget, if it's not already and use a flag, setstate if team changes and do comparison on the flag.

Something like this:

bool isTeamsEmpty = true;

if(teams.isEmpty == false)
{
   setState()
   {
      isTeamEmpty = false;
   }
}

return isTeamEmpty
            ? const Loader()
            : Container(
                // something
              );
Related