I'm new in using flutter_bloc and currently facing an issue in my project.
So, i have bloc class like this:
class TestBloc extends Bloc<TestEvent, TestState> {
@override
TestState get initialState => InitialTestState();
@override
Stream<TestState> mapEventToState(
TestEvent event,
) async* {
if (event is StateOneEvent) {
yield StateOne("one");
} else if (event is StateTwoEvent) {
yield StateTwo("two");
}
}
}
/// === Event class
abstract class TestEvent extends Equatable {
const TestEvent();
}
class StateOneEvent extends TestEvent {
@override
List<Object> get props => [];
}
class StateTwoEvent extends TestEvent {
@override
List<Object> get props => [];
}
// == State class
abstract class TestState extends Equatable {
const TestState();
}
class InitialTestState extends TestState {
@override
List<Object> get props => [];
}
class StateOne extends TestState {
final String value;
StateOne(this.value);
@override
List<Object> get props => [value];
}
class StateTwo extends TestState {
final String value;
StateTwo(this.value);
@override
List<Object> get props => [value];
}
And here is my main function:
void main() {
runApp(
MultiBlocProvider(
providers: [
BlocProvider(create: (context) {
return TestBloc();
}),
],
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: '/',
routes: {
'/': (context) => FirstPage(),
'/second_page': (context) => SecondPage(),
},
);
}
}
So here i have two page, FirstPage and SecondPage like here. Each of this class will show current state of the bloc.
class FirstPage extends StatefulWidget {
@override
_FirstPageState createState() => _FirstPageState();
}
class _FirstPageState extends State<FirstPage> {
@override
void initState() {
super.initState();
BlocProvider.of<TestBloc>(context).add(StateOneEvent());
}
@override
Widget build(BuildContext context) {
return Scaffold(body: BlocBuilder<TestBloc, TestState>(
builder: (_, state) {
String value = '-';
if (state is StateOne) {
value = state.value;
} else if (state is StateTwo) {
value = state.value;
}
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(value),
RaisedButton(
onPressed: () {
Navigator.pushNamed(context, '/second_page');
},
child: Text('Goto Second Page'),
)
],
),
);
},
));
}
}
class SecondPage extends StatefulWidget {
@override
_SecondPageState createState() => _SecondPageState();
}
class _SecondPageState extends State<SecondPage> {
@override
void initState() {
super.initState();
BlocProvider.of<TestBloc>(context).add(StateTwoEvent());
}
@override
Widget build(BuildContext context) {
return Scaffold(body: BlocBuilder<TestBloc, TestState>(
builder: (_, state) {
String value = '-';
if (state is StateOne) {
value = state.value;
} else if (state is StateTwo) {
value = state.value;
}
return Center(
child: Text(value),
);
},
));
}
}
Both of them use same bloc (TestBloc). In the initial state of FirstPage i tried to dispatch event to TestBloc to change current state to StateOne and display the current state value in a Text. So for FirstPage it will show one.
After that, i tried to navigate to SecondPage which have almost the same as FirstPage. In the inital state of SecondPage i tried to dispatch event to TestBloc to change current state to StateTwo so it will then show two in the Text.
But the problem is when i navigate.pop from SecondPage or pressing back button, the text inside FirstPage become two. Seems that TestBloc streams is not closed when i navigate to new page.
My expectation is FirstPage is supposed to still with its last state which is displaying one
and not affected by what i do in SecondPage.
How to address this issue?
Thanks
[UPDATE]
I tried to changed SecondPage like here so it will have another bloc scope. This solves the problem actually, but does this seems to be the right and good solution?
class SecondPage extends StatefulWidget {
@override
_SecondPageState createState() => _SecondPageState();
}
class _SecondPageState extends State<SecondPage> {
TestBloc testBloc = TestBloc();
@override
void initState() {
super.initState();
testBloc.add(StateTwoEvent());
}
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => testBloc,
child: Scaffold(body: BlocBuilder<TestBloc, TestState>(
builder: (_, state) {
String value = '-';
if (state is StateOne) {
value = state.value;
} else if (state is StateTwo) {
value = state.value;
}
return Center(
child: Text(value),
);
},
)),
);
}
}