Flutter如何从启动页(splash screen)跳转页面 出现Navigator上下文错误怎么解决
问题修复方案
错误原因
报错核心是你调用Navigator时使用的context属于
MainPage组件,而Navigator是在MaterialApp内部才初始化的,MainPage是MaterialApp的父组件,父组件的context无法访问到子组件内部的Navigator实例。
另外你在build方法中直接调用异步方法getRedirectPage,会导致页面每次重绘都重复发起请求,属于逻辑错误。
修复步骤
- 第一步:调整组件结构,将
MaterialApp提到最外层,把启动页逻辑拆分为独立的子组件,保证跳转用的context在MaterialApp的子树内 - 第二步:将异步请求逻辑移到
initState中,避免重复执行
修复后完整代码
void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: 'ID - IoT', theme: ThemeData( primarySwatch: Colors.blue, ), home: const SplashScreen(), ); } } class SplashScreen extends StatefulWidget { const SplashScreen({Key? key}) : super(key: key); @override _SplashScreenState createState() => _SplashScreenState(); } class _SplashScreenState extends State<SplashScreen> { @override void initState() { super.initState(); // 初始化阶段调用跳转逻辑,仅执行一次 getRedirectPage(context); } Future<void> getRedirectPage(BuildContext context) async { await initializeSharedPrefs(); ServerResponse serverResponse = await makeRequestToServer(null); if (serverResponse.state.isNotEmpty) { if (serverResponse.state == "true") { if (serverResponse.redirect == "login") { Navigator.of(context).pushReplacement( PageRouteBuilder(pageBuilder: (_,__,___)=> const LoginPage()) ); } else { Navigator.of(context).pushReplacement( PageRouteBuilder(pageBuilder: (_,__,___)=> const Homepage()) ); } } else { showAlertDialog(context, "Server error", "Something went wrong: ${serverResponse.msg}"); } } else { showAlertDialog(context, "Server error", "Something went wrong: ${serverResponse.msg}"); } } @override Widget build(BuildContext context) { return Container( decoration: const BoxDecoration( image: DecorationImage( image: AssetImage('assets/images/background.jpeg'), fit: BoxFit.cover, ), ), ); } }
额外优化建议
- 可以给跳转逻辑加个最低展示时长,避免请求响应太快导致启动页一闪而过体验差,可搭配
Future.delayed控制至少显示1~2秒 - 建议给请求逻辑加异常捕获,避免接口超时、报错导致页面卡住
内容的提问来源于stack exchange,提问作者Mattia
相关产品推荐
相关产品推荐

