How to use bloc pattern between two screens
Asked Answered
E

2

8

my main.dart file looks like this.

home: MultiBlocProvider(
      providers: [
        BlocProvider<UserBloc>(
          create: (BuildContext context) =>   UserBloc()..add(GetUser(userId:"5e0b62023b75dd60e22edaad")),
        ),
         BlocProvider<TodoBloc>(
           create: (BuildContext context)=> TodoBloc()..add(AddTodoEvent()),)
      ],
      child: FirstScreen(),
    ),

I want to navigate to the second screen on button press in FirstScreen.

var router = new MaterialPageRoute(
      builder: (BuildContext context){
        return BlocProvider<UserBloc>(
          create: (BuildContext context) =>   UserBloc(),
          child: SecondScreen(),
        );
      });
  Navigator.of(context).push(router);

It works fine,but it will create new UserBloc initial state. What I want is to get the currect state on UserBlog.

I tried this

UserBloc userBloc = BlocProvider.of<UserBloc>(context);
BlocProvider<CounterBloc>(
  bloc: userBloc,
  child: SecondScreen()
 )

bloc gives an error. Is there any way to navigate to the SecondScreen and have the same state.

Ewan answered 7/1, 2020 at 17:38 Comment(0)
S
19

Every time you call BlocProvider, you create new instance of bloc class.

To work with the same bloc instance, you need to create it once, and put it before routing after that you will have access to it via context.

import 'package:bloc/bloc.dart';

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiBlocProvider(
      providers: [
        BlocProvider<BlocSample>(
          create: (BuildContext context) => BlocSample(),
        ),
      ],
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: FirstScreen(),
      ),
    );
  }
}

class BlocSample extends Bloc<EventSample, String> {
  @override
  String get initialState => 'initial state';

  @override
  Stream<String> mapEventToState(
    EventSample event,
  ) async* {
    yield 'changed state';
  }
}

class EventSample {}

class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocBuilder<BlocSample, String>(
      builder: (context, state) {
        return Scaffold(
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(state),
                RaisedButton(
                  child: Text('change status'),
                  onPressed: () => BlocProvider.of<BlocSample>(context).add(
                    EventSample(),
                  ),
                ),
                RaisedButton(
                  child: Text('change route'),
                  onPressed: () => Navigator.of(context).push(
                    MaterialPageRoute(
                      builder: (_) => SecondScreen(),
                    ),
                  ),
                )
              ],
            ),
          ),
        );
      },
    );
  }
}

class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocBuilder<BlocSample, String>(
      builder: (context, state) {
        return Scaffold(
          body: Center(child: Text(state)),
        );
      },
    );
  }
}

enter image description here

Shostakovich answered 7/1, 2020 at 19:5 Comment(6)
how can i pass the global instance to the secondScreen using Navigator .Ewan
You don't need to pass it, it's already there in the context. You need to just use BlocBuilder, BlocListener or BlocProvider depending on your needs. Let me make a small example to show you. I'll update the anwer.Shostakovich
@Shostakovich can I use this method with over 20+ Blocs ? or it will give a bad performance?Janka
@WailHayaly, sure don't forget to check official documentation bloclibrary.devShostakovich
@kherel ... you said "Every time you call BlocProvider, you create new instance of bloc class." There are TWO constructors for BlocProvider ... one of them creates a new instance, the other uses a reference to an existing instance.Preference
What if I want to do without wrapping the whole app on it?Scourings
Z
0

please check this blogpost https://blog.geekyants.com/state-management-in-flutter-7df833e6f3bd once. It was explaining the clear process about the bloc pattern using without taking any help of plugin support. Please let me know, if you need any more help.

Zelikow answered 7/1, 2020 at 18:59 Comment(3)
i tried above link. Didn't help, new bloc instance created everytime.Aspiration
@HarshalBhatt Please let me know your actual requirement of using bloc.Zelikow
I want to share BLoC between 2 screens of pageview control without any plugin. 1st and 2nd tab for product and cart concept. I've initiate BloCProvider on a root of PageView widget and accessing bloc in tab1 and tab2 screen. But both screen creating their own new instance.Aspiration

© 2022 - 2024 — McMap. All rights reserved.