티스토리 뷰

플러터에서 게비게이터(navigator)로 화면을 이동하는 코드를 작성하고 실행하였는데, 아래와 같은 에러가 발생했다.

The following assertion was thrown while handling a gesture: Navigator operation requested with a context that does not include a Navigator. The context used to push or pop routes from the Navigator must be that of a widget that is a descendant of a Navigator widget.

 

에러 내용을 해석하면, '네비게이터에서 이동하려면 사용되는 콘텍스트(context)는 네비게이터 위젯의 하위 위젯 콘텍스트어야 한다'라고 되어 있다.

 

다음 코드는 에러가 발생했던 코드가 된다.

import 'package:flutter/material.dart';

void main() {
  runApp(const FirstPage());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text("First Page")),
        body: Center(
          child: ElevatedButton(
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) {
                    return const SecondPage();
                  },
                ),
              );
            },
            child: const Text("Go to Second Page"),
          ),
        ),
      ),
    );
  }
}

 

 

MaterialApp은 네비게이션을 처리하기 위해서 앱의 전체적인 구조를 설정하고, 네비게이션 스택(Navigation Stack)을 관리하며, 라우팅(Routing)을 지원한다. 그래서 MaterialApp에는 Navigator가 포함되어 있다.

 

따라서 위의 코드는 MaterialApp과 Navigator가 같은 컨텍스트를콘텍스트를 참조하게 되어서 에러가 발생하는 것이다. Navigator가 MaterialApp과 다른 콘텍스트를 참조하기 위해서는 해결할 수 있는 두 가지 방법이 있다.

 

1. Builder를 사용해서 새로운 컨텍스트를 Navigator에 전달한다.

2. Navigator를 사용하는 위젯을 새로운 위젯으로 만들어서 MaterialApp과 분리한다.

 

 

그리고 이 코드의 또다른 문제점은 MaterialApp 위젯이 FirstPage에 포함되어 있는 상태에서 네비게이션으로 화면을 이동한다. 화면이 하나라면 문제가 없는 코드이지만 화면이 여러 개를 가지는 앱이라면 MaterialApp 위젯은 앱 전체를 감싸는 최상위 위젯으로 사용되어야 한다. 그러면 이동한 화면의 위젯도 main()의 MaterialApp의 하위 위젯이 된다. 즉, MaterialApp은 최상위 위젯이 된다.

 

 

따라서 MaterialApp을 main()으로 옮겨서 앱 전체를 감싸는 최상위 위젯으로 수정하자. 그러면 자연스레 MaterialApp과 Navigator의 콘텍스트로 분리가 된다.

import 'package:flutter/material.dart';

void main() {
  runApp(const MaterialApp(
    home: FirstPage(),
  ));
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("First Page")),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) {
                  return const SecondPage();
                },
              ),
            );
          },
          child: const Text("Go to Second Page"),
        ),
      ),
    );
  }
}

 

 

앱을 실행할 때는 핫리로드가 아닌 run으로 실행해야 한다. 핫리로드로 실행하면 다음같은 에러가 발생한다!

The following assertion was thrown building Scaffold(dirty, state: ScaffoldState#4f5c6(tickers: tracking 2 tickers)): No MediaQuery widget ancestor found.

 

 

 

댓글
공지사항