Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter build called multiple times

I have a bottom nav bar that has a list page that uses a bloc for the state.

class _MainPageState extends State<MainPage> {
  int _index = 0;
  @override
  Widget build(BuildContext context) {
    final List<Widget> _widgets = [
      const ListPage(),
      Scaffold(),
      Scaffold(),
      
    ];

    return Scaffold(
        body: IndexedStack(
          index: _index,
          children: _widgets,
        ),
      bottomNavigationBar: BottomNavigationBar(
    ...


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

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (_) =>
          getIt<ListBloc>()..add(const ListEvent.load(limit: 10)),
      child: SafeArea(
        child: Scaffold(
          appBar: AppBar(),
          body: const List(),
        ),
      ),
    );
  }
}

The problem is build is beeing called 4 times. This causes the event fetching the list 4 times.

Don't know where to add the event to prevent re-builds.

If I add the event in statefull widget's initState. Bloc does not recognize ListBloc beeing in the context when fetching the bloc down the widget tree.

like image 228
loki Avatar asked Nov 23 '20 00:11

loki


People also ask

How many times build is called in Flutter?

The build method is called any time you call setState , your widget's dependencies update, or any of the parent widgets are rebuilt (when setState is called inside of those). Your widget will depend on any InheritedWidget you use, e.g. Theme. of(context) , MediaQuery.

Why is FutureBuilder called multiple times?

Why FutureBuilder Called again? This is due to state changes that come if setState() called, which triggers build() method, and due to this inside widgets will be re-initialize again.

How do you call a build function in Flutter?

How to Call Method after Build in Flutter. To call method after build is completed, the idea is to use the addPostFrameCallback callback and add your method inside it. As its name suggests it allows you to register a callback after the last frame of your page is drawn.


1 Answers

The best way is to add event in initState of you main route (Route that contains Bottom Navigation). As shown in below code.

class _MainPageState extends State<MainPage> {
  int _index = 0;

  @override
  void initState() {
    super.initState();
    getIt<ListBloc>().add(const ListEvent.load(limit: 10));
  }

  @override
  Widget build(BuildContext context) {
    final List<Widget> _widgets = [
      const ListPage(),
      Scaffold(),
      Scaffold(),
      
    ];

    return Scaffold(
        body: IndexedStack(
          index: _index,
          children: _widgets,
        ),
      bottomNavigationBar: BottomNavigationBar(
    ...


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

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (_) =>
          getIt<ListBloc>(),
      child: SafeArea(
        child: Scaffold(
          appBar: AppBar(),
          body: const List(),
        ),
      ),
    );
  }
}
like image 182
Taha Malik Avatar answered Sep 28 '22 18:09

Taha Malik