繁体   English   中英

Flutter 闪屏错误 - 使用不包含导航器的上下文请求导航器操作。 我该如何解决这个错误

[英]Flutter splash screen error - Navigator operation requested with a context that does not include a Navigator. How can I solve this error

编辑:(main.dart)添加了实际启动应用程序的哨兵

 Future<void> main() async {
   await SentryFlutter.init(
    (options) {
      options.dsn = _sentryDSN;
      // Set tracesSampleRate to 1.0 to capture 100% of        transactions for performance monitoring.
      // We recommend adjusting this value in production.
      options.tracesSampleRate = _sentryTracesSampleRate;
      options.attachStacktrace = true;
      options.enableAppLifecycleBreadcrumbs = true;
      },
   appRunner: () => runApp(const SplashScreen()),
  );

   // or define SENTRY_DSN via Dart environment variable (--dart-define)
  }

flutter 的新功能,为使用 MaterialApp 构建但出现错误的应用程序创建启动画面。 如果没有 onPress function,我该如何解决这个问题

错误: 在此处输入图像描述

发生异常。 FlutterError(使用不包含导航器的上下文请求的导航器操作。用于从导航器推送或弹出路由的上下文必须是作为导航器小部件后代的小部件的上下文。)

import 'package:flutter/material.dart';
import 'package:loopcycle/screens/loopcycle_main.dart';

class SplashScreen extends StatefulWidget {
  const SplashScreen({Key? key}) : super(key: key);

  @override
  State<SplashScreen> createState() => _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen> {
  @override
  void initState() {
  super.initState();
  _navigateToMainApp();
}

void _navigateToMainApp() async {
  await Future.delayed(const Duration(milliseconds: 2000), () {
    Navigator.pushReplacement(context,
      MaterialPageRoute(builder: (context) => const LoopcycleMainApp()));
  });
}

@override
Widget build(BuildContext context) {
  return MaterialApp(
    home: Builder(
      builder: (context) => const Center(
            child: Text("test"),
          )),
    );
  }
}

先感谢您。

编辑:在您提供有关代码的更多信息后,我更改了解决方案。

发生此错误是因为您使用的上下文中没有Navigator ,这可能是因为您获取上下文的小部件是MaterialApp()小部件的父级,要解决它,您应该创建另一个小部件是MaterialApp()的子组件而不是使用父组件,让我举个例子:

void main() {
    runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: GestureDetector(
        onTap: () => Navigator.of(context).push(
          MaterialPageRoute(
            builder: (context) => SomeWidget(),
          ),
       ),
        child: Container(
          height: 300,
          width: 300,
          color: Colors.red,
        ),
      ),
    );
  }
}

这可能会出错,因为您正在使用作为MaterialApp()小部件父级的小部件的上下文,要解决它只需创建另一个作为MaterialApp()子级的小部件。

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: AnotherWidget(),
    );
  }
}

class AnotherWidget extends StatelessWidget {
  const AnotherWidget({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GestureDetector(
        onTap: () => Navigator.of(context).push(
          MaterialPageRoute(
            builder: (context) => SomeWidget(),
          ),
        ),
        child: Container(
          height: 300,
          width: 300,
          color: Colors.red,
        ),
      ),
    );
  }
}

我在玩你的代码,并为你修复了它,基本上有两种方法可以解决它,你可以在调用runApp() function 中的SplashScreen() MaterialApp() ,如下所示:

import 'package:flutter/material.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:loopcycle/screens/loopcycle_main.dart';

Future<void> main() async {
  await SentryFlutter.init(
    (options) {
      options.dsn = _sentryDSN;
      // Set tracesSampleRate to 1.0 to capture 100% of        transactions for performance monitoring.
      // We recommend adjusting this value in production.
      options.tracesSampleRate = _sentryTracesSampleRate;
      options.attachStacktrace = true;
      options.enableAppLifecycleBreadcrumbs = true;
    },
    appRunner: () => runApp(
      const MaterialApp(
        home: SplashScreen(),
      ),
    ),
  );

  // or define SENTRY_DSN via Dart environment variable (--dart-define)
}

class SplashScreen extends StatefulWidget {
  const SplashScreen({Key? key}) : super(key: key);

  @override
  State<SplashScreen> createState() => _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen> {
  @override
  void initState() {
    super.initState();
    _navigateToMainApp();
  }

  void _navigateToMainApp() async {
    await Future.delayed(const Duration(milliseconds: 2000), () {
      Navigator.pushReplacement(context,
          MaterialPageRoute(builder: (context) => const LoopcycleMainApp()));
        });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Builder(
          builder: (context) => const Center(
                child: Text("test"),
              )),
    );
  }
}

或者您可以创建一个中间小部件来保存MaterialApp() ,然后在这个小部件内您可以调用SplashScreen() ,如下所示:

import 'package:flutter/material.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:loopcycle/screens/loopcycle_main.dart';

Future<void> main() async {
  await SentryFlutter.init(
    (options) {
      options.dsn = _sentryDSN;
      // Set tracesSampleRate to 1.0 to capture 100% of        transactions for performance monitoring.
      // We recommend adjusting this value in production.
      options.tracesSampleRate = _sentryTracesSampleRate;
      options.attachStacktrace = true;
      options.enableAppLifecycleBreadcrumbs = true;
    },
    appRunner: () => runApp(const MyApp()),
  );

  // or define SENTRY_DSN via Dart environment variable (--dart-define)
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: SplashScreen(),
    );
  }
}

class SplashScreen extends StatefulWidget {
  const SplashScreen({Key? key}) : super(key: key);

  @override
  State<SplashScreen> createState() => _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen> {
  @override
  void initState() {
    super.initState();
    _navigateToMainApp();
  }

  void _navigateToMainApp() async {
    await Future.delayed(const Duration(milliseconds: 2000), () {
      Navigator.pushReplacement(context,
          MaterialPageRoute(builder: (context) => const LoopcycleMainApp()));
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Builder(
          builder: (context) => const Center(
                child: Text("test"),
              )),
    );
  }
}

在第二个解决方案中,中间小部件是MyApp()小部件,在我看来,我认为这个解决方案是解决您的问题的最佳解决方案,因为如果您想根据不同的状态加载不同的屏幕,对于例子:

如果用户已登录,则加载主页,如果用户未登录,则加载注册页面。

当你有这个包含MaterialApp()的中间小部件时,这样做或类似的事情会容易得多,你甚至可以创建一些逻辑来集成启动画面,但我不知道你想要实现什么,所以选择您认为最适合您的问题的解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM