how to use same bloc in multiple widgets

2,594

Use BlocProvider.value named constructor

class CounterPage extends StatefulWidget {
  @override
  _CounterPageState createState() => _CounterPageState();
}

class _CounterPageState extends State<CounterPage> {
  CounterBloc counterBloc;

  @override
  void initState() {
    super.initState();
    counterBloc = BlocProvider.of<CounterBloc>(context);
  }

  @override
  void dispose() {
    counterBloc.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Counter')),
      body: BlocBuilder<CounterBloc, int>(
        builder: (_, count) {
          return Column(
            children: <Widget>[
              Text(
                '$count',
                style: const TextStyle(fontSize: 24.0),
              ),
              RaisedButton(
                child: Text("Recreating state"),
                onPressed: () {
                  Navigator.push(
                    context,
                    MaterialPageRoute(
                      builder: (context) => BlocProvider<CounterBloc>.value(
                        value: counterBloc,
                        child: ThirdPage(),
                      ),
                    ),
                  );
                },
              ),
              RaisedButton(
                child: Text("Getting errorBlocProvider.of() called  "),
                onPressed: () {
                  Navigator.push(
                    context,
                    MaterialPageRoute(
                      builder: (context) => BlocProvider<CounterBloc>.value(
                        value: counterBloc,
                        child: FourthPage(),
                      ),
                    ),
                  );
                },
              )
            ],
          );
        },
      ),
      // ....
    );
  }
}
Share:
2,594
arjun more
Author by

arjun more

Updated on December 20, 2022

Comments

  • arjun more
    arjun more over 1 year

    I'm facing issue in my current project so created this question im unable to get same bloc state in other widget i tried this https://github.com/felangel/bloc/issues/74#issuecomment-457968962 but i'm getting BlocProvider.of() called with a context that does not contain a Bloc of type CounterBloc. error if add Provider again in other widget another state is created for that page how to use same bloc state in different widgets.

    
    import 'dart:async';
    
    import 'package:flutter/material.dart';
    
    import 'package:flutter_bloc/flutter_bloc.dart';
    
    class SimpleBlocDelegate extends BlocDelegate {
      @override
      void onEvent(Bloc bloc, Object event) {
        print(event);
        super.onEvent(bloc, event);
      }
    
      @override
      void onTransition(Bloc bloc, Transition transition) {
        print(transition);
        super.onTransition(bloc, transition);
      }
    
      @override
      void onError(Bloc bloc, Object error, StackTrace stacktrace) {
        print(error);
        super.onError(bloc, error, stacktrace);
      }
    }
    
    void main() {
      BlocSupervisor.delegate = SimpleBlocDelegate();
      runApp(App());
    }
    
    class App extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return BlocProvider(
          create: (_) => ThemeBloc(),
          child: BlocBuilder<ThemeBloc, ThemeData>(
            builder: (_, theme) {
              return MaterialApp(
                title: 'Flutter Demo',
                home: BlocProvider(
                  create: (_) => CounterBloc(),
                  child: CounterPage(),
                ),
                theme: theme,
              );
            },
          ),
        );
      }
    }
    
    class CounterPage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: const Text('Counter')),
          body: BlocBuilder<CounterBloc, int>(
            builder: (_, count) {
              return Column(
                children: <Widget>[
                  Text(
                    '$count',
                    style: const TextStyle(fontSize: 24.0),
                  ),
                  RaisedButton(
                    child: Text("Recreating state"),
                    onPressed: () {
                      Navigator.push(
                        context,
                        MaterialPageRoute(builder: (context) => ThirdPage()),
                      );
                    },
                  ),
                  RaisedButton(
                    child: Text("Getting errorBlocProvider.of() called  "),
                    onPressed: () {
                      Navigator.push(
                        context,
                        MaterialPageRoute(builder: (context) => FourthPage()),
                      );
                    },
                  )
                ],
              );
            },
          ),
          floatingActionButton: Column(
            crossAxisAlignment: CrossAxisAlignment.end,
            mainAxisAlignment: MainAxisAlignment.end,
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.symmetric(vertical: 5.0),
                child: FloatingActionButton(
                  heroTag: "btn3",
                  child: const Icon(Icons.add),
                  onPressed: () =>
                      context.bloc<CounterBloc>().add(CounterEvent.increment),
                ),
              ),
              Padding(
                padding: const EdgeInsets.symmetric(vertical: 5.0),
                child: FloatingActionButton(
                  heroTag: "dd",
                  child: const Icon(Icons.remove),
                  onPressed: () =>
                      context.bloc<CounterBloc>().add(CounterEvent.decrement),
                ),
              ),
              Padding(
                padding: const EdgeInsets.symmetric(vertical: 5.0),
                child: FloatingActionButton(
                  heroTag: "btn2",
                  child: const Icon(Icons.brightness_6),
                  onPressed: () => context.bloc<ThemeBloc>().add(ThemeEvent.toggle),
                ),
              ),
            ],
          ),
        );
      }
    }
    
    **/// new state is created i want to use previous state**
    ///
    ///
    class ThirdPage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return BlocProvider(
          create: (_) => CounterBloc(),
          child: BlocBuilder<CounterBloc, int>(
            builder: (BuildContext context, int count) {
              return Scaffold(
                backgroundColor: Colors.white,
                body: Center(child: Text('$count')),
              );
            },
          ),
        );
      }
    }
    
    
    
    **/// getting error BlocProvider.of() called with a context that does not co**
    ///
    ///
    class FourthPage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        final CounterBloc _counterBloc = BlocProvider.of<CounterBloc>(context);
        return BlocBuilder<CounterBloc, int>(
          bloc: _counterBloc,
          builder: (BuildContext context, int count) {
            return Scaffold(
              backgroundColor: Colors.white,
              body: Center(child: Text('$count')),
            );
          },
        );
      }
    }
    
    enum CounterEvent { increment, decrement }
    
    class CounterBloc extends Bloc<CounterEvent, int> {
      @override
      int get initialState => 0;
    
      @override
      Stream<int> mapEventToState(CounterEvent event) async* {
        switch (event) {
          case CounterEvent.decrement:
            yield state - 1;
            break;
          case CounterEvent.increment:
            yield state + 1;
            break;
          default:
            throw Exception('oops');
        }
      }
    }
    
    enum ThemeEvent { toggle }
    
    class ThemeBloc extends Bloc<ThemeEvent, ThemeData> {
      @override
      ThemeData get initialState => ThemeData.light();
    
      @override
      Stream<ThemeData> mapEventToState(ThemeEvent event) async* {
        switch (event) {
          case ThemeEvent.toggle:
            yield state == ThemeData.dark() ? ThemeData.light() : ThemeData.dark();
            break;
        }
      }
    }