Going back to previous screen by using back button is making lose BLOC State. Flutter
I'm currently using flutter_bloc: ^8.1.3
and go_router: ^7.1.1
. I have two screens, one is
display items screen
and another one is add items screen
. In display items screen i'm using initState()
to load the items data with the help of bloc and it is working fine. But when i navigate to add items screen and click on back button, the display items screen is showing white screen but it was suppose to show the data. Here is my code.
display_items_Screen.dart
class DisplayItemsScreen extends StatefulWidget {
const DisplayItemsScreen({super.key});
@override
State<DisplayItemsScreen> createState() => _DisplayItemsScreenState();
}
class _DisplayItemsScreenState extends State<DisplayItemsScreen> {
@override
void initState() {
super.initState();
context.read<DisplayItemsBloc>().add(DisplayItemsLoadEvent());
}
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () => context
.push("/add-items")
,
child: const Icon(Icons.add),
),
appBar: AppBar(
title: const Text("Display Items"),
),
body: BlocConsumer<DisplayItemsBloc, DisplayItemsState>(
listener: (context, state) {
if (state is DisplayItemsErrorState) {
showSnackBar("Something went wrong! please try again.");
}
},
builder: (context, state) {
if (state is DisplayItemsLoadingState) {
return const LoadingView();
} else if (state is DisplayItemsLoadedState) {
final categories = state.userProductCategories;
return DisplayItem(categories: categories); // stateless widget GridView.builder()
} else { // it is running this else condition when navigated using back button
return SizedBox.shrink();
}
},
),
);
}
}
add_items_screen.dart
class AddItemsScreen extends StatefulWidget {
const AddItemsScreen({super.key});
@override
State<AddItemsScreen> createState() => _AddItemsScreenState();
}
class _AddItemsScreenState extends State<AddItemsScreen> {
@override
void initState() {
super.initState();
context.read<AddItemsBloc>().add(AddItemsLoadEvent());
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Add Items"),
),
body: BlocConsumer<AddItemsBloc, AddItemsState>(
listener: (context, state) {
if (state is AddItemsErrorState) {
showSnackBar("Something went wrong! please try again.");
}
},
builder: (context, state) {
if (state is AddItemsLoadingState) {
return const LoadingView();
} else if (state is AddItemsLoadedState) {
final items = state.loadedItems;
return AddItem(categories: items);
} else {
return SizedBox.shrink();
}
},
),
);
}
}
router.dart
final navigatorKey = GlobalKey<NavigatorState>();
class AppRoutes {
static routes() {
return GoRouter(
initialLocation: "/",
navigatorKey: navigatorKey,
routes: <RouteBase>[
GoRoute(
path: "/display-items",
pageBuilder: (BuildContext _, GoRouterState state) {
return CupertinoPage(
child: const DisplayItemsScreen(),
key: state.pageKey,
restorationId: state.pageKey.value,
);
},
),
GoRoute(
path: "/add-items",
pageBuilder: (BuildContext _, GoRouterState state) {
return CupertinoPage(
child: const AddItemsScreen(),
key: state.pageKey,
restorationId: state.pageKey.value,
);
},
)
],
);
}
}
bloc_providers.dart
class BlocProviders {
final DisplayItemsRepository _displayItemsRepository = DisplayItemsRepository();
final AddItemsRepository _addItemsRepository =
AddItemsRepository();
blocs() {
return [
BlocProvider<DisplayItemsBloc>(
create: (context) => DisplayItemsBloc(repository: _displayItemsRepository),
),
BlocProvider<AddItemsBloc>(
create: (context) => AddItemsBloc(repository: _addItemsRepository),
),
];
}
}
main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Hive.initFlutter();
final BlocProviders blocProviders = BlocProviders();
runApp(
MultiBlocProvider(
providers: blocProviders.blocs(),
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
MyApp({super.key});
final _router = AppRoutes.routes();
@override
Widget build(BuildContext context) {
return MaterialApp.router(
scaffoldMessengerKey: snackbarKey,
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: AppTheme.lightTheme,
darkTheme: AppTheme.darkTheme,
themeMode: ThemeMode.light,
routerConfig: _router,
// routeInformationParser: AppRoutes.routes().routeInformationParser,
// routeInformationProvider: AppRoutes.routes().routeInformationProvider,
// routerDelegate: AppRoutes.routes().routerDelegate,
);
}
}
Maybe In your DisplayItemsBloc
code some state is triggering.
If you provide your bloc code it would be good to understand.
But you can use buildWhen function in your BlocConsumer to stop building unnecessary states:
buildWhen: (previous, current) =>
current is DisplayItemsLoadingState || current is DisplayItemsLoadedState
and you can make your builder function like this:
builder: (context, state) {
if (state is DisplayItemsLoadedState) {
final categories = state.userProductCategories;
return DisplayItem(categories: categories);
} else {
return const LoadingView();
}
},