Flutter - trigger navigation when Provider variable changes
Solution 1
Instead of trying to navigate to a new view what you should do is display the loading splash screen if you are still waiting for data and once that changes display your main home view, like this:
import 'package:catalogo/firebase/ProductData.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class Main extends StatefulWidget {
@override
_MainState createState() => _MainState();
}
class _MainState extends State<Main> {
bool shouldProceed = Provider.of<ProductData>(context, listen: true).shouldProceed;
@override
Widget build(BuildContext context) {
if(shouldProceed){
return Home();
}else{
return RouteSplash();
}
}
}
Solution 2
Use BlocListener as in this example:
BlocListener(
bloc: BlocProvider.of<DataBloc>(context),
listener: (BuildContext context, DataState state) {
if (state is Success) {
Navigator.of(context).pushNamed('/details');
}
},
child: BlocBuilder(
bloc: BlocProvider.of<DataBloc>(context),
builder: (BuildContext context, DataState state) {
if (state is Initial) {
return Text('Press the Button');
}
if (state is Loading) {
return CircularProgressIndicator();
}
if (state is Success) {
return Text('Success');
}
if (state is Failure) {
return Text('Failure');
}
},
}
)
Source: https://github.com/felangel/bloc/issues/201
William Terrill
Updated on December 16, 2022Comments
-
William Terrill over 1 year
I'm trying to show a splash screen on initial app startup until I have all of the data properly retrieved. The retrieval is done by a class called "ProductData" As soon as it's ready, I want to navigate from the splash page to the main screen of the app.
Unfortunately, I can't find a good way to trigger a method that runs that kind of Navigation and listens to a Provider.
This is the code that I'm using to test this idea. Specifically, I want to run the command Navigator.pushNamed(context, 'home'); when the variable shouldProceed becomes true. Unfortunately, the code below gives me the error, "setState() or markNeedsBuild() called during build."
import 'package:catalogo/firebase/ProductData.dart'; import 'package:flutter/material.dart';= import 'package:provider/provider.dart'; class RouteSplash extends StatefulWidget { @override _RouteSplashState createState() => _RouteSplashState(); } class _RouteSplashState extends State<RouteSplash> { bool shouldProceed = false; @override Widget build(BuildContext context) { shouldProceed = Provider.of<ProductData>(context, listen: true).shouldProceed; if (shouldProceed) { Navigator.pushNamed(context, 'home'); <-- The error occurs when this line is hit. } else { return Scaffold( body: Center( child: CircularProgressIndicator(), ), ); } } }
Is there a better way to navigate to a page based on listening to the results of a provider?