TLDR: Add:
WidgetsBinding.instance.addPostFrameCallback((_) =>
context.go('/Home'));
to the FutureBuilder
I managed to reproduce the problem with this example. Let's take a look.
If you run this code:
import 'package:flutter/material.dart';
void main() => runApp(MainApp());
class MainApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(body: Test()),
);
}
}
class Test extends StatelessWidget {
const Test({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: printHello(),
builder: (context, snapshot) {
if (snapshot.hasData) {
Navigator.push(
context, MaterialPageRoute(builder: (context) => HomePage()));
return Text(snapshot.data.toString());
} else if (snapshot.hasError) {
return Text("error");
} else {
return Center(child: CircularProgressIndicator());
}
});
}
}
Future<String> printHello() async {
return Future.value("Hello");
}
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(body: const Text("home page"));
}
}
You'll see an error:
setState() or markNeedsBuild() called during build.
So, to fix the problem, you need to use WidgetsBinding.instance.addPostFrameCallback
:
WidgetsBinding.instance.addPostFrameCallback((_) =>
Navigator.push(context, MaterialPageRoute(builder: (context) {
return HomePage();
})));
but for your example for go_router
, add this line:
WidgetsBinding.instance.addPostFrameCallback((_) =>
context.go('/Home'));
Complete working example:
import 'package:flutter/material.dart';
void main() => runApp(MainApp());
class MainApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(body: Test()),
);
}
}
class Test extends StatelessWidget {
const Test({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: printHello(),
builder: (context, snapshot) {
if (snapshot.hasData) {
WidgetsBinding.instance.addPostFrameCallback((_) =>
Navigator.push(context, MaterialPageRoute(builder: (context) {
return HomePage();
})));
return Text(snapshot.data.toString());
} else if (snapshot.hasError) {
return Text("error");
} else {
return Center(child: CircularProgressIndicator());
}
});
}
}
Future<String> printHello() async {
return Future.value("Hello");
}
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(body: const Text("home page"));
}
}
See also
setState() or markNeedsBuild called during build