簡體   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