본문 바로가기

flutter

context 없이 navigation 구현하기

 

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (context) => UserProvider()),
      ],
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        theme: ThemeData(
          primaryColor: ColorPalette.white,
          scaffoldBackgroundColor: ColorPalette.white,
          visualDensity: VisualDensity.adaptivePlatformDensity,
        ),
        routes: pages,
        initialRoute: Routes.test.path,
      ),
    );
  }
}

페이지 이동을 할때는 Navigator.of(context).pushNamed를 이용해서 페이지 이동을 하였다. 네비게이션을 할 때 context가 필요하여 제약이 걸렸다. 비즈니스 로직에서 네비게이션을 해야하는 상황이 발생하였다. 그래서 context 인자를 ui에서 비즈니스 로직으로 넘겨서 수행을 하는데 깨끗하지 못해 context 없이 네비게이션을 하는 방법에 대해 알아보겠다.

 

1. MaterialApp의 navigatorKey

MaterialApp에는 navigatorKey라는 property가 있다. 이 property를 주게 되면 Navigation.of를 사용할필요가 없이 navigatiorKey.currentState로 네비게이션을 할 수 있게 된다. 이 때 onGenerateRoute라는 property가 있는데 이 property를 주어야 네비게이션이 된다.

 

2. NavigationService 구현

먼저 NavigationService를 싱글톤으로 구현한다.

class NavigationService {

  static final NavigationService _instance = NavigationService._internal();
  NavigationService._internal();

  factory NavigationService() => _instance;

}

그 다음 NavigatiorState 유형의 GlobalKey를 추가한다.

class NavigationService {

  static final NavigationService _instance = NavigationService._internal();
  NavigationService._internal();

  factory NavigationService() => _instance;

  final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
  
  get key => _navigatorKey;

}

마지막으로 Navigation Service를 추가

class NavigationService {

  static final NavigationService _instance = NavigationService._internal();
  NavigationService._internal();

  factory NavigationService() => _instance;

  final GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>();

  get key => _navigatorKey;

  dynamic back({Object? arguments}) {
    return _navigatorKey.currentState?.pop(arguments);
  }

  Future pushNamed(String routeName, {Object? arguments}) async {
    return _navigatorKey.currentState?.pushNamed(routeName, arguments: arguments);
  }

  Future pushNamedAndRemoveAll(String routeName, {Object? arguments}) async {
    return _navigatorKey.currentState?.pushNamedAndRemoveUntil(routeName, (route) => false,arguments: arguments);
  }

}

 

3. onGenerateRoute 구현

routes.dart 파일을 생성하여 아래와 같이 작성

var onGenerateRoute = (RouteSettings settings) {
  switch(settings.name){
    case 'main':
      return MaterialPageRoute(builder: (context) => MainPage());
    case '/login':
      return MaterialPageRoute(builder: (context) => LoginPage());
    case '/join':
      return MaterialPageRoute(builder: (context) => JoinPage());
    case '/uiTest':
      return MaterialPageRoute(builder: (context) => UITest());
    case '/project/create':
      return MaterialPageRoute(builder: (context) => ProjectCreatePage());
    case '/project/detail':
      return MaterialPageRoute(builder: (context) => ProjectDetailPage());
    case '/my':
      return MaterialPageRoute(builder: (context) => MyPage());
  }
  return null;
};

4. MeterialApp

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (context) => UserProvider()),
      ],
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        theme: ThemeData(
          primaryColor: ColorPalette.white,
          scaffoldBackgroundColor: ColorPalette.white,
          visualDensity: VisualDensity.adaptivePlatformDensity,
        ),
        navigatorKey: NavigationService().key,
        initialRoute: Routes.test.path,
        onGenerateRoute: onGenerateRoute,
      ),
    );
  }
}

'flutter' 카테고리의 다른 글

freezed live template로 쉽게 생성하기  (0) 2022.08.11
expandable fab  (0) 2022.06.15
singleton  (0) 2022.06.14
flutter 해당 위젯 코드 쉽게 찾기  (0) 2022.05.31
BoxConstraints forces an infinite width  (0) 2022.05.26