Don't think! Just do it!

종합 IT 기술 정체성 카오스 블로그! 이... 이곳은 어디지?

Flutter/Flutter Study

[소셜차트] 앱 제작기 #7. 네비게이션 시스템 뒤집어 엎기.

방피터 2022. 11. 2. 12:11

Getx로는 제대로 된 Bottom tab navigator를 구현하기 힘들다는 블로그를 봤는데... 개뿔.. 잘만하더라....

일단 기본 네비게이터로 구현했던 nested navigation 시스템에서는 좀 있어 보일라고 NavigationTree.dart라는 파일에서 모든 네비게이션 시스템이 관리되도록 하려고 했는데.... 👇👇 참... 등신짓이었어.

2022.10.21 - [Flutter/Flutter Project] - [소셜차트] 앱 제작기 #3. Navigation 시스템 구성

 

[소셜차트] 앱 제작기 #3. Navigation 시스템 구성

2022.10.14 - [Flutter/Flutter Project] - [소셜차트] 앱 제작기 #2. 기본 설정 [소셜차트] 앱 제작기 #2. 기본 설정 우선 프로젝트 생성. 👇 %flutter create --org com.petercircuitsoft socialchart --org 옵션으로 com.petercircu

engschool.tistory.com

nested navigator에서는 같은 여러 스크린이 각각 다른 네비게이터에 배치될 수 있는데 이 때도 문제가 심각해지더라고.. 뿐만 아니라 각 스크린 argument 전달에도 문제가 있었고, 페이지를 변경하거나 확장하는 것도 개판이었고... 그야 말로 대 환장 파티... 에휴.....

그래도 이번 기회에 view와 controller를 분리시키는 getx의 의도를 조금 깨달은 거 같아서 다행이긴 해. 역시 고생을 해야 늘어 ㅋㅋ

우선 파일 하나로 구현했던 bottom tab navigator를 tab별로 파일을 분리해서 심플하게 변경했어👇  

class NavigatorMain extends GetView<MainNavigatorController> {
  const NavigatorMain({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      body: Obx(
        () => IndexedStack(
          index: controller.currentIndex.index,
          children: const [
            TabNavigatorHome(),
            TabNavigatorExplore(),
            TabNavigatorNotice(),
            TabNavigatorProfile(),
          ],
        ),
      ),
      bottomNavigationBar: Obx(() => controller.isBottomTabVisible
          ? BottomNavigationBar(
              type: BottomNavigationBarType.fixed,
              items: const [
                BottomNavigationBarItem(
                  icon: Icon(CupertinoIcons.home),
                  label: "홈",
                ),
                BottomNavigationBarItem(
                  icon: Icon(CupertinoIcons.search),
                  label: "탐색",
                ),
                BottomNavigationBarItem(
                  icon: Icon(CupertinoIcons.bell),
                  label: "알림",
                ),
                BottomNavigationBarItem(
                  icon: Icon(CupertinoIcons.person),
                  label: "내정보",
                ),
              ],
              currentIndex: controller.currentIndex.index,
              onTap: (index) => controller.currentIndex = NavKeys.values[index],
            )
          : Container(height: 0)),
    );
  }
}

기존에 사용하던 Stack + OffStage 조합으로 구현했던 tab별 navigator는 IndexedStack하나로 간단하게 변경했고 bottom tab navigator를 감추고 싶을 경우도 있을거 같아서 get controller에 isBottomTabVisible를 하나 추가했어.

그리고 각 navigator의 MaterialPageRoute는 GetPageRoute로 변경하고 각 스크린에 binding을 통해서 controller를 붙여줬어. 이렇게 하는 사람들이 많아서 따라해봤는데 확실히 편하고 구조적으로도 안정되어 있는 거 같아.👇👇

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

  @override
  Widget build(BuildContext context) {
    return Navigator(
      key: Get.nestedKey(NavKeys.home.index),
      initialRoute: ScreenHome.routeName,
      onGenerateRoute: ((settings) {
        switch (settings.name) {
          case ScreenHome.routeName:
            return GetPageRoute(
              page: () => ScreenHome(navKey: NavKeys.home),
            );
          case ScreenInsightCard.routeName:
            return GetPageRoute(
                page: () => ScreenInsightCard(navKey: NavKeys.home));
          case ScreenProfile.routeName:
            var args = settings.arguments;
            return GetPageRoute(
              page: () =>
                  ScreenProfile(userId: args.toString(), navKey: NavKeys.home),
              binding: ScreenProfileBinding(navKey: NavKeys.home),
            );
          case ScreenChart.routeName:
            return GetPageRoute(
              page: () => ScreenChart(navKey: NavKeys.home),
              binding: ScreenChartBinding(navKey: NavKeys.home),
            );
          case ScreenWrite.routeName:
            return GetPageRoute(
              page: () => ScreenWrite(navKey: NavKeys.home),
              binding: ScreenWriteBinding(navKey: NavKeys.home),
            );
          default:
            return null;
        }
        // });
      }),
    );
  }
}

 

get으로 router 시스템을 변경하면서 스크린이나 그 컨트롤러를 여러 navigator에서 재활용하는 게 매우 간편해졌고 스크린에 argument를 전달하는 것도 마찬가지로 쉬워졌어. 이렇게 변경하는 과정에서 각 screen이나 navigator는 binding 파일과 controller 파일을 가지도록 만들고 있어. controller나 binding이 당장 필요하지 않은 건 만들지 않았지만 나중에는 다 만들어 둘라고 ㅋㅋ 왜? 걍 버릇을 들이려고 하는 것도 있고 언제 또 controller가 필요할 지 모르는데 그 때마다 허둥지둥하고 싶지 않아서..

Flutter 프로젝트 폴더, 파일 이름

그리고 파일이랑 폴더 이름도 많이 변경했어. 몰랐는데 dart에서 파일, 폴더 작명은 소문자에 "_" (under score)를 사용하는 걸 추천하더라고 👇👇 뭐 이유가 있겠지...하고 나도 따르고 있어.

https://dart.dev/guides/language/effective-dart/style

 

Effective Dart: Style

Formatting and naming rules for consistent, readable code.

dart.dev

기본적으로 UpperCamelCase, lowerCamelCase 그리고 lowercase_with_underscores 이렇게 3가지가 있는데 위에서 언급한 것처럼 파일, 폴더, 라이브러리는 lowercase_with_underscores를 사용하고 Class 같은 type을 나타내는 애들은 UpperCamelCase, 그리고 그 type의 instance나 constant는 lowerCamelCase 사용을 추천한다고 되어 있어.

3가지 명명 방식

아무리 혼자 작업하더라고 지킬 건 지켜야겠지 ㅎㅎ 암튼 더 자세한 건 위 링크에 있는 문서를 보라구.

암튼 그래서 결국 navigation 시스템 다 갈아엎고 스크린들도 좀 더 추가하고 firebase model 만들고 하는 과정에 있어. 여기까지 하는데 약 2주 좀 넘게 걸렸네.. 아이고 언제 다 만드냐 ㅋㅋㅋㅋ

지금까지 한거~

아이고 우리 아들 운다~ 안녕~!

반응형

'Flutter > Flutter Study' 카테고리의 다른 글

[Flutter] Bad state: Future already completed  (0) 2022.11.10
[Flutter] getx page&controller 재사용  (0) 2022.11.02
[Flutter] loading 화면  (0) 2022.10.25
[Flutter] Firebase auth email link login  (0) 2022.10.21
[Flutter] GetX  (0) 2022.10.17