Flutter
패키지
Go Router

Go Router

구글 플러터 팀에서 공식으로 지원 (opens in a new tab)하는 패키지
Documentation (opens in a new tab)

Initalization

// 기존의 MaterialApp에 .route를 추가해줌 
MaterialApp.router(
  // 3.2 버전 이후로 사용해줘야 함
  // 라우트 정보를 전달하는 역할을 함
  routeInformationProvider: _router.routeInformationProvider,
  // URI String을 상태 및 Go Router에서 사용할 수 있는 형태로 반환해주는 함수
  routeInformationParser: _router.routeInformationParser,
  // 위에서 변경된 값으로 실제로 어떤 라우트를 보여줄지 정하는 함수
  routerDelegate: _router.routerDelegate,
);

페이지 이동

Go

// namedPush
context.goNamed(ThreeScreen.routeName);
// stack push
context.go('/one/two/three'); 

go router를 이용해서 nesting된 페이지를 push 하게 되면 상위 페이지들이 스택처럼 쌓이게 됨.

Push

아래와 같이 nesting된 라우트가 없는 코드의 경우 go를 사용해서 화면 전환을 시도해도 하위에 아무런 화면이 쌓이지 않게 됨.
아래 코드에서, Restaurant Detail Screen은 상위에 RootTab에 nesting 되어 있지만 BasketScreen은 nesting된 라우트가 없음.

그럴 때, push 메서드를 사용하게 되면 현재 화면에다가 Screen을 Stack처럼 올리는 방식을 사용할 수 있음.

context.push(NextScreen());
// named route 방식
context.pushNamed(NextScreen.routeName);

Pop

context.pop();

Shell Route with Riverpod

Shell Route with Riverpod 사용 방법 (opens in a new tab)

redirect

참고 Repo (opens in a new tab)

redirect는 특정한 상황이 있을 때 특정한 페이지로 이동을 시켜주는 역할을 한다.
아래에서 보여질 예제는 로그인이 되어있는지 확인하고 로그인이 되어있으면 HomePage로 이동하고 로그인이 되어있지 않으면 /로 이동하게 되는 코드이다.
처음에는 goRouterProvider를 build 내에서 watch를 하고 있으면 goRouterProvider 함수 내에서 watch 하는 값이 변경됨에 따라서 동작이 달라질거라고 생각을 했는데, 그건 아니었다.


아래와 같이 refreshListenable을 사용해서 ChangeNotifier를 넣어줘서 해당 ChangeNotifier가 변경될 때마다 redirect 함수가 실행된다.

goRouterProvider

ChangeNotifier

class GoRouterRefreshStream extends ChangeNotifier {
  late final Stream<User?> _stream;
  late final StreamSubscription<User?> _streamSubscription;
 
  GoRouterRefreshStream(this._stream) {
    notifyListeners();
    _streamSubscription = _stream.asBroadcastStream().listen((event) {
      // authStateChange가 stream으로 들어오게 되고 
      // 이 stream이 변경될 때마다 notifyListeners를 통해서 GoRouterRefreshStream이 변경됨을 알려줌.
      notifyListeners();
    });
  }
 
  @override
  void dispose() {
    _streamSubscription.cancel();
    super.dispose();
  }
}

Error

No Such Method Error

다음과 같은 에러는 잘못된 context에서 go router를 불러오고 있기 때문에 발생하는 에러임. :::warning 예외가 발생했습니다.
NoSuchMethodError (NoSuchMethodError: Class 'SliverMultiBoxAdaptorElement' has no instance method 'goNamed'.
Receiver: Instance of 'SliverMultiBoxAdaptorElement'
Tried calling: goNamed("restaruantDetail", params: _LinkedHashMap len:1)) :::

아래의 예제에서는 PaginationListView의 itemBuilder의 context에서 goNamed를 불러오고 있음.

따라서 다음의 context를 다음과 같이 수정해주면

정상적으로 동작하는 모습을 볼 수 있음. 👇