개발노트

78. [Flutter] GetX GetView로 View - Controller - Binding 패턴으로 만들기 본문

앱 개발/Flutter

78. [Flutter] GetX GetView로 View - Controller - Binding 패턴으로 만들기

mroh1226 2024. 8. 9. 00:57
반응형

View, Controller, Binding 생성을 도와주는 Extension 설치

 

GetX Snippets
get~ 문자로 간단하게 생성 가능


GetView 란?

  • GetView는 GetX 패키지에서 제공하는 Flutter 위젯의 일종으로, 특정 컨트롤러에 쉽게 접근할 수 있도록 설계된 클래스다.
  • **GetView<T>**에서 T는 특정 컨트롤러 타입을 의미하며, 이 컨트롤러를 사용하여 UI와 로직을 연결함
  • GetView는 컨트롤러에 쉽게 접근할 수 있도록 하며, controller 속성으로 컨트롤러의 메서드, 속성에 접근할 수 있음
  • 이는 특히, 단순한 UI와 컨트롤러의 바인딩을 효율적으로 처리하고자 할 때 유용

기존 소스에서 패턴 적용해보기

이제, 이전에 포스팅했던 Navigation 페이지를 View - Controller - Binding 패턴으로 바꿔본다.

- 이전 포스팅: https://mroh1226.tistory.com/229

 

77. [Flutter] GetX 의 Named Route 사용하여, 화면 전환되는bottomNavigationBar만들기

GetX와 animated_bottom_navigation_bar 을 이용하여 하단탭 페이지전환 기능 만들기.!만들면서 Named Route 사용법을 익혀본다. GetX 설치: https://pub.dev/packages/get/install get install | Flutter packageOpen screens/snackbars/

mroh1226.tistory.com

View - Controller - Binding 패턴 사용을 보여주기 위해 page에 대한 소스만 집중해본다.

기존 소스 (이전포스팅 소스) 설명 (패턴 적용 X)
1. Stateless 위젯의 Build 안에서 Get.LazyPut 으로 Controller를 등록한다.
2. 등록된 Controller를 사용한다.
*GetBuilder<Controller> 는 Controller 값 변경을 실시간 감시하여 다시 랜더링한다.
class NavigationPage extends StatelessWidget {
  const NavigationPage({super.key});

  @override
  Widget build(BuildContext context) {
    Get.lazyPut(
      () => NaviController(),
    );
    return GetBuilder<NaviController>(
      builder: (controller) {
        return Scaffold(
            body: Center(
              child: IndexedStack(
                index: controller.selectedIndex,
                children: const [
                  ExplorePage(),
                  TripsPage(),
                  ProfilePage(),
                  WishlistPage(),
                ],
              ),
            ),
            floatingActionButtonLocation:
                FloatingActionButtonLocation.centerDocked,
            floatingActionButton: FloatingActionButton(
                shape: const CircleBorder(),
                backgroundColor: Colors.orange,
                child: const Icon(
                  Icons.inbox,
                  color: Colors.white,
                ),
                onPressed: () {
                  Get.to(() => const InboxPage());
                }),
            bottomNavigationBar: AnimatedBottomNavigationBar(
                backgroundColor: const Color.fromARGB(255, 55, 29, 150),
                gapLocation: GapLocation.center,
                notchSmoothness: NotchSmoothness.verySmoothEdge,
                rightCornerRadius: 32,
                leftCornerRadius: 32,
                icons: const [
                  Icons.explore,
                  Icons.airplanemode_active,
                  Icons.person,
                  Icons.list,
                ],
                activeIndex: controller.selectedIndex,
                activeColor: Colors.amber,
                onTap: (index) => controller.setIndex(index)));
      },
    );
  }
}

class NaviController extends GetxController {
  var selectedIndex = 0;
  void setIndex(int index) {
    selectedIndex = index;
    update();
  }
}

 


이제 기존 소스에서 View - Controller - Binding 패턴으로 변경하기 시작.!

1. navigation_page.dart (View) (소스상 page로 표현)
class NavigationPage extends GetView<NaviController> {
  const NavigationPage({super.key});

  @override
  Widget build(BuildContext context) {
    return GetBuilder<NaviController>(
      builder: (controller) {
        return Scaffold(
            body: Center(
              child: IndexedStack(
                index: controller.selectedIndex,
                children: const [
                  ExplorePage(),
                  TripsPage(),
                  ProfilePage(),
                  WishlistPage(),
                ],
              ),
            ),
            floatingActionButtonLocation:
                FloatingActionButtonLocation.centerDocked,
            floatingActionButton: FloatingActionButton(
                shape: const CircleBorder(),
                backgroundColor: Colors.orange,
                child: const Icon(
                  Icons.inbox,
                  color: Colors.white,
                ),
                onPressed: () {
                  Get.to(() => const InboxPage());
                }),
            bottomNavigationBar: AnimatedBottomNavigationBar(
                backgroundColor: const Color.fromARGB(255, 55, 29, 150),
                gapLocation: GapLocation.center,
                notchSmoothness: NotchSmoothness.verySmoothEdge,
                rightCornerRadius: 32,
                leftCornerRadius: 32,
                icons: const [
                  Icons.explore,
                  Icons.airplanemode_active,
                  Icons.person,
                  Icons.list,
                ],
                activeIndex: controller.selectedIndex,
                activeColor: Colors.amber,
                onTap: (index) => controller.setIndex(index)));
      },
    );
  }
}

 

위 기존 소스에서 아래와 같이 작업

  1.  StatelessWidget 을 GetView로 변경하고 제네릭으로 <NaviController> 를 등록해준다.
    > Get.find()를 호출할 필요가 없어짐
  2. binding 파일에서 따로 Controller를 Get.LazyPut 할거기 때문에, Widget Build 안의 Get.lazyPut( () => NaviController(), ); 삭제
  3. Controller 부분도 파일 생성 후 따로 관리 하기 때문에 삭제

 

2. navigation_controller.dart (Controller) 새로 .dart 파일 생성
class NaviController extends GetxController {
  var selectedIndex = 0;
  void setIndex(int index) {
    selectedIndex = index;
    update();
  }
}
  • view 부분에서 삭제한 Controller를 GetxController 따로 파일을 생성하여 추가해줌

 

3. navigation_binding.dart (Binding) 새로 .dart 파일 생성
class NaviBinding extends Bindings {
  @override
  void dependencies() {
    // NaviController를 지연 로딩 방식으로 등록
    // Get.lazyPut<T>() 메서드는 컨트롤러나 서비스 등을 필요할 때까지 생성하지 않고,
    // 실제로 사용될 때 생성하여 메모리에 등록
    Get.lazyPut<NaviController>(() => NaviController());
  }
}
  • Bindings를 상속받는 NaviBinding class 생성후 Get.LazyPut으로 Controller 등록
  • dependencies 메서드
    • dependencies() 메서드는 Bindings 클래스를 상속받을 때 반드시 구현해야 하는 메서드
    • 이 메서드는 페이지가 로드될 때 어떤 의존성(컨트롤러, 서비스 등)을 주입할지 정의
4. router.dart
class Routes {
  static List<GetPage> pages = [
    GetPage(
      name: '/',
      page: () => const NavigationPage(),
      binding: NaviBinding(),	//binding: 속성에 NaviBinding 등록
      transition: Transition.rightToLeft,
    ),
    ...
    ]
}
  • Routes 에 NavigationPage 페이지에 binding: 속성에 3.에서 만들어준 Binding class 등록

 

 

끝.! 적용된 패턴은 다르지만 빌드된 모습은 동일하기 때문에 생략.!
반응형
Comments