이코노딩

[Flutter] GetX로 상태관리하기 본문

언어/Dart & Flutter

[Flutter] GetX로 상태관리하기

떼이로 2023. 1. 4. 17:20

▶상태관리

플러터에서 상태변화는 setState()메소드를 호출하여 변화 시켜주는게 기본

하지만, setState는 화면 전체를 리빌드 시키기 때문에 상태변화가 일어나지 않는 부분 까지도 리빌드가 이루어져, 자원낭비가 높다.

이를 위한 여러 라이브러리가 있는데 그 중, GetX에 대하여 공부해보겠다.

 

▶GetX

https://pub.dev/packages/get

 

get | Flutter Package

Open screens/snackbars/dialogs without context, manage states and inject dependencies easily with GetX.

pub.dev

GetX를 사용하면서 느낀건, context를 안쓰는게 너무 편하다는 점이다. 

예를 들어 화면 라우팅을 할 경우,

Navigator.push(context, MaterialPageRoute(builder: (context)=> const SecondPage())

이런 식으로 페이지 라우팅 코드가 작성되지만, GetX의 경우는

Get.to(()=>const SecondPage())

코드 감소가 확실히 눈에 띄게 줄어든다.

 

그리고 GetX자체에서 지원되는 여러 라이브러리를 편하게 사용할 수 있다.

 

GetXController

GetX는 StatefulWidget 보단 StatelessWidget을 이용하는 걸 추천한다. (그렇다고, Stateful을 사용 못하는건 아니다)

StatelessWidget으로 뷜드된 윗젯에서 상태변화가 일어나는 걸 감지하고 변화시 update를 시켜준다.

 

이러한 상태변화를 관리해 줄 컨트롤러가 필요로한데 이를 GetXController를 상속 받을 Class를 만들어 준 후 사용해주면된다. 

예를 들어 간단하게 정수형 변수 n을 출력하는 위젯이 있다고 가정해보자

class Home extends StatelessWidget {
  const Home({Key? key, required this.title}) : super(key: key);
  final String title;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Container(
        alignment: Alignment.center,
        child: Text(n),
      ),
    );
  }
}

여기서 n은 정수형 변수이다 하지만 이 변수는 controller를 통해 관리 되어야하므로 GetXController를 상속 받은 클래스에 선언해야 한다.

class HomeController extends GetxController{
  int n = 0;

  pressBtn(){
    n++;
  }
}

정수형 변수 n과 버튼을 눌렀을 때 n을 증가시켜줄 함수를 하나 만들었다. 

이제 컨트롤러를 위젯에 불러와 사용해야하는데 어떤식으로 불러올까?

 

✔️ Get.put

GetX라이브러리 중 지원하는 put메소드를 이용하는 방법이다. 

class Home extends StatelessWidget {
  const Home({Key? key, required this.title}) : super(key: key);
  final String title;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Container(
        alignment: Alignment.center,
        child: Text(Get.put(HomeController()).n.toString()),
      ),
    );
  }
}
class Home extends StatelessWidget {
  Home({Key? key, required this.title}) : super(key: key);
  final String title;
  final controller = Get.put(HomeController());
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Container(
        alignment: Alignment.center,
        child: Text(controller.n.toString()),
      ),
    );
  }
}

위와 같은 방법으로 사용할 부분에만 선언하여도 되고 자주 쓰이는 경우 변수에 담아서 사용도 가능하다 이러면 버튼을 눌렀을 때, 변화가 일어나나?

❌ 일어나지 않는다.

변수 선언은 했지만, 이를 감지하고 있지 않기 때문이다. 

상태변화를 감지하게 하기 위해서는 2가지 방법이 있다.

 

✅Rx자료형

Rx자료형으로 변수를 선언해주는 방법이다.

class HomeController extends GetxController{
  RxInt n = 0.obs;

  pressBtn(){
    n.value++;
  }
}

RxInt로 n을 선언해준 뒤 초기값뒤에 .obs를 붙여 감지함을 알린다.

Rx자료형은 변수내에 값을 value로 가지기 때문에 변수를 이용하려면 .value를 통해서 값에 접근해야한다.

다시 위젯으로 넘어가서

Container(
            alignment: Alignment.center,
            width: Get.width,
            child: Obx(()=> Text(Get.put(HomeController()).n.value.toString()))
          ),

감지하고자 하는 위젯을 Obx로 감싸주면 끝난다.

버튼을 눌러보면 잘 동작함을 알 수있다.

 

✅GetBuilder

GetBuilder를 이용하여 감지하는 방법이다.

class HomeController extends GetxController{
  int n = 0;

  pressBtn(){
    n++;
    update();
  }
}

가장 중요한 점은 변화를 일으킬 때 마다 update()함수를 사용하여 상태변화를 알려줘야한다는 점이다.

update()함수가 빠진다면 변화가 안일어난다.

Container(
            alignment: Alignment.center,
            width: Get.width,
            child: GetBuilder<HomeController>(
              init: Get.put(HomeController()),
                builder: (context) {
                return Text('${Get.put(HomeController()).n}');
              }
            )
          ),

위젯에서 변화가일어나는 부분을 GetBuilder<T>로 감싸준뒤,

init에서 컨트롤러를 불러와줘야한다.(안 불러오면 null 에러 뜸)

 

그리고 동작해 보면 Rx와 똑같이 잘 동작한다. 

 

개인적으로 Obx를 이용하는게 좀 더 간편하고 코드도 간결해서 사용하기 편했다.

다음은 GetX에서 지원하는 위젯들을 정리해야겠다.