개발/Flutter

Flutter GetX 패턴으로 프로젝트 구성해보기(1) - GetX란?

T'Challa 2021. 6. 7. 23:51

GetX란?

1. Performance(성능)

 

GetX는 Streams 나 ChangeNotifier 를 사용하지 않음

Resource 사용을 최소화 하려함

 

2. Productivity(생산성)

 

컨트롤러를 메모리에서 제거하려고 하지 않아도 됨

메모리에 계속 유지시키고 싶다면, "permanent: true" 를 의존성에 선언해주면 됨

사용하지 않는 resource들은 기본적으로 메모리에서 제거됨

문법이 간단함

 

3. Organization(조직화)

 

route 사이를 이동하는데 context가 필요없음

presentation logic, business logic을 visualization layer에서 decoupling 시킬 수 있음

MultiProvider를 통해 Controllers/Models/Bloc 클래스를 위젯 트리에 주입할 필요가 없다.

이를 GetX가 자체 DI기능을 통해 완벽하게 decoupling 시켜준다.

controller를 접근할 때도 context가 필요없음

GetX는 View, presentation logic, business logic, dependency injection, navigation 을 따로 사용할 수 있음

 

위 3가지에 초점을 둔 채, State management(상태 관리), dependency injection(의존성 주입), route management(경로 관리)를 도와주는 Flutter 라이브러리

GetX는 기능들이 분리되어 있어 사용하고 싶은 기능들만 사용가능

예를들어 GetX의 Statemanagement 기능만 쓰면 해당 부분만 컴파일됨

GetX 설치

pubspec.yaml 파일에 dependency 추가:

dependencies:
  get:

flutter pub add get

위의 명령어를 실행해도 자동으로 dependency 추가됨

아래처럼 import:

import 'package:get/get.dart';

Counter app 비교

Step1. MaterialApp -> GetMaterialApp

// 원래
void main() {
  runApp(MyApp());
}
// GetX 사용
void main() {
  runApp(GetMaterialApp(home: Home());
}

GetMaterialApp은 MaterialApp을 자식으로 하는 사전 구성된 Widget

GetMaterialApp은 route 생성하고 주입할 수 있음

Get을 상태 관리나 의존성 관리에만 사용하려면 GetMaterialApp을 사용할 필요 없음

GetMaterialApp은 routes나 snackbars, i18n, bottomSheets, dialogs, 고수준 apis, 컨텍스트 없이 사용하기 등에 필요함

Step2. 비즈니스 로직 클래스 생성 및 모든 변수 배치

// increment 메소드가 View와 같이 State Class 내부에 존재
class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
      // ...
  }
}
// GetX 사용 : Controller 클래스로 비즈니스 로직 분리
class Controller extends GetxController{
    var count = 0.obs; // .obs 사용하면 provider처럼 notify 처럼 사용 가능
    increment() => count++;
}

Step3. View 생성

StatelessWidget 을 사용하고 RAM에 올림, Get을 사용하면 StatefulWidget이 필요없음

// 원래
@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
// GetX 사용한 View
class Home extends StatelessWidget {
  @override
  Widget build(context) {
    // Get.put()을 사용하여 클래스를 인스턴스화하여 모든 하위 경로에 사용할 수 있도록 함
    final Controller c = Get.put(Controller());

    return Scaffold(
        // Obx(()=>) 를 사용하면 count가 변경됐을 때 Text를 갱신할 수 있다.
        appBar: AppBar(title: Obx(() => Text("Clicks: ${c.count}"))),

        // Get.to(Other()) 를 사용하여 Navigator.push를 사용한 것처럼 화면 이동 가능하다.
        body: Center(
            child: ElevatedButton(
                child: Text("Go to Other"), onPressed: () => Get.to(Other()))),
        floatingActionButton: FloatingActionButton(
            child: Icon(Icons.add), onPressed: c.increment));
  }
}

class Other extends StatelessWidget {
  // Get 이 자동으로 Controller 를 찾아주는 Get.find()
  final Controller c = Get.find();

  @override
  Widget build(context) {
    // Get.find() 를 통해 찾은 Controller로 count 변수 접근
    return Scaffold(body: Center(child: Text("${c.count}")));
  }
}

확실히 View 와 Controller 클래스를 나누어 사용할 수 있으니 보기도 편하고 익숙하다.
그리고 재사용성이 확실히 좋을 것 같다.

출처 https://pub.dev/packages/get