I have this code. In summary, I am learning Flutter and I created this code just to practice. The goal is to type in a TextField and then press a FloatingActionBotton and onPressed it updates a text widget. I used BloC as a state manager. Then, just to test Flutter behavior, I created a new screen to go back and forth and see it works. I was surprise to see that I lost my state in my home page and that I can’t even update the text widget anymore after pressing the FloatingActionButton. What happened?
When I come back to home screen, the text widget is gone and when I press the floatingactionbutton (add icon) I get an exception BlocProvider.of() called with a context that does not contain a ExampleBloc.
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:equatable/equatable.dart';
void main() {
runApp(MaterialApp(
home: BlocProvider.value(
value: ExampleBloc(),
child: Home(),
),
));
}
class Home extends StatefulWidget {
Home({Key? key}) : super(key: key);
@override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
late TextEditingController teste;
late String lol;
@override
void initState() {
teste = TextEditingController();
lol = 'ola';
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: <Widget>[
TextField(
controller: teste,
),
Center(child: BlocBuilder<ExampleBloc, ExampleState>(
builder: (context, state) {
return Text(state.exampleString ?? 'null');
},
))
],
),
floatingActionButton: Row(
children: [
FloatingActionButton(
onPressed: () {
lol = teste.text;
BlocProvider.of<ExampleBloc>(context)
.add(ExampleUseEvent(exampleString: lol));
},
child: Icon(Icons.add),
),
FloatingActionButton(
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) => HEHE()),
),
child: Text('next screen'),
),
FloatingActionButton(
onPressed: () => Navigator.of(context).pop(),
child: Text('pop'),
),
],
),
);
}
@override
void dispose() {
teste.dispose();
super.dispose();
}
}
class HEHE extends StatelessWidget {
const HEHE({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: const Center(child: Text('teste')),
floatingActionButton: Row(
children: [
FloatingActionButton(
onPressed: () => Navigator.of(context).push(
MaterialPageRoute(builder: (context) => Home()),
),
child: Text('next screen')),
],
),
);
}
}
class ExampleBloc extends Bloc<ExampleEvent, ExampleState> {
ExampleBloc() : super(ExampleState()) {
on<ExampleUseEvent>(exampleFuncion);
}
Future<void> exampleFuncion(
ExampleUseEvent event,
Emitter<ExampleState> emit,
) async {
emit(state.copyWith(
exampleString: event.exampleString,
));
}
}
abstract class ExampleEvent {}
class ExampleUseEvent extends ExampleEvent {
final String exampleString;
ExampleUseEvent({required this.exampleString});
}
class ExampleState extends Equatable {
final String? exampleString;
ExampleState({
this.exampleString,
});
ExampleState copyWith({
String? exampleString,
}) {
return ExampleState(
exampleString: exampleString ?? this.exampleString,
);
}
@override
List<Object?> get props => [
exampleString,
];
}
2
Answers
Look how I use bloc in Flutter, I think your error is because you don’t have a state of your bloc, so, the data reset.
example_state.dart
example_bloc.dart
example_event.dart
Example bloc only exists in fist page when it is provided by MaterialApp.
Switch MaterialApp and BlocProvider.value to get the desired result.
MaterialApp contains Navigator which contains list of PageRoutes when pages are pushed. If BlocProvider will be defined before MaterialApp, it will be available to all the pages.