[Flutter] GetX 와 UI 업데이트
개요
Flutter 에서는 위젯을 상태(State)에 따라 StatelessWidget
과 StatefulWidget
으로 분류해서 정의하고 위젯의 상태를 변경하여 UI 를 업데이트할 수 있는 setState
함수를 지원합니다. 하지만 이 함수에 대해서 플러터 공식 문서에서 이런 경고 내용을 볼 수 있습니다.
Avoid overly large single Widgets with a large build() function. Split them into different Widgets based on encapsulation but also on how they change
하나의 큰 위젯, build 함수를 피하라고 써있습니다. setState 의 작동방식은 결국 build 함수를 다시 돌려 rebuild 하는 것이기 때문이죠. 이 방식은 업데이트가 필요하지 않는 위젯도 rebuild 를 하게 되는 문제가 있습니다.
setState 함수의 문제점
다음 코드는 플러터를 시작했을 때 기본으로 작성되는 Counter 위젯입니다.
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
_counter++;
});
},
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
MyHomePage
는 StatefulWidget
으로 상태, State
를 가집니다. _counter
라는 상태는 FloatingActionButton
이 클릭됐을 때 setState
함수로 상태가 변경이 됩니다.
프로파일링을 돌려보겠습니다.
버튼을 눌렀을 때 rebuild 된 횟수를 보면 화면상 변경된것은 Text 뿐이지만 AppBar
나 FloationActionButton
도 rebuild 가 됐습니다. 즉 UI업데이트가 낭비되고 있는 것입니다. 이를 해결하기 위해선 build
함수를 매우 작게 나눠야 하고 setState
를 까먹지 않게 호출해줘야 합니다. 결국 "데이터가 변경 되면 변경 된 위젯만 자동으로 UI를 업데이트"하고 싶은 니즈가 생길것입니다. 이런 니즈를 충족할 수 있는 좋은 라이브러리가 GetX 라이브러리입니다.
Getx 라이브러리
GetX
라이브러리의 설명에 따르면
GetX는 Flutter를 위한 매우 가볍고 강력한 솔루션입니다. 고성능 상태 관리, 지능형 종속성 주입 및 빠르고 실용적인 라우트 관리가 결합되어 있습니다.
라고 설명합니다. 이번 포스팅에서는 고성능 상태 관리라는 것에 초점을 맞춰보겠습니다.
기본 내용
GetX
라이브러리는StatefulWidget
사용을 지양합니다.GetX
라이브러리는 .obs 연산자를 이용해 아주 간단하게 변수를Observable
로 바꿀 수 있습니다.
우선 기존 Counter 를 GetX 로 변경한 코드부터 보겠습니다.
class GetMyHomePageController extends GetxController {
RxInt counter = 0.obs;
increase() {
counter.value += 1;
}
}
class GetMyHomePage extends StatelessWidget {
const GetMyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
Widget build(BuildContext context) {
return GetBuilder<GetMyHomePageController>(
init: GetMyHomePageController(),
builder: (controller) => Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Obx(
() => Text(
'${controller.counter.obs}',
style: Theme.of(context).textTheme.headline4,
),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => controller.increase(),
tooltip: 'Increment',
child: const Icon(Icons.add),
),
),
);
}
}
GetxController
우선 GetxController
라는 것이 등장했습니다. GetX
는 StatelessWidget
을 사용하기 때문에 이 위젯에서는 데이터에 따른 UI 만을 보여주는것이 좋습니다. 따라서 상태가 변할 수 있는 데이터들을 따로 컨트롤러에서 관리를 하는데 MVVM 패턴의 ViewModel 과 유사하다고 생각하시면 됩니다.
GetBuilder
를 사용해서 init 에 사용하고자 할 컨트롤러를 정의를 해주면 builder
함수에서 해당 컨트롤러를 사용할 수 있습니다. 이 밖에도 GetX
에서는 GetxController
를 관리하는 아주 많은 방법을 제공해주므로 다음에 포스팅하도록 하겠습니다.
.obs
Observable
을 변환시켜주는 연산자입니다. 데이터가 변경이 되면 자동으로 Notify
를 보내 UI 를 업데이트 할 수 있습니다. 예제에서는 increase
함수에서 counter.value += 1로 데이터를 업데이트 하고 있습니다.
.obs
객체가 Notify 를 보내면 UI 에서는 업데이트를 해야합니다. 하지만 실제 View 는 StatelessWidget
이므로 업데이트를 하지 않고 업데이트를 하고 싶은 위젯을 Obx 위젯으로 감싸야합니다. 이 때 Obx(builder)
안에 .obs
객체가 없다면 에러가 나니 주의가 필요합니다.
프로파일링
똑같이 버튼을 눌렀을 때 rebuild 횟수 입니다. 데이터에 바인딩 되어있는 Text 뷰와 그걸 감싸는 Obx 위젯만 rebuild 됐고 다른 AppBar
나 FloatingActionButton
은 rebuild 되지 않았습니다. 이 때문에 GetX
는 고성능 상태 관리를 지원할 수 있게 됩니다.
주의할 점
Obx
를 Text 가 아닌 상위 위젯인 Scaffold에 감싸게 된다면 마찬가지로 화면에 변경점이 없더라도 Obx
로 감싼 모든 위젯들이 rebuild 가 됩니다. 예를들어 스켈레톤 UI 를 사용할 때 페이지 이동 후 데이터를 받아올 때까지 로딩화면을 보여줘야하므로 전체를 Obx
객체를 감싸게 됩니다. 하지만 그 이후로는 전체를 rebuild 하지 않고 부분적으로 rebuild 하고 싶을 수 있는데 이 문제는 Obx
객체 안에 Obx
객체를 넣어서 해결할 수 있습니다. 다음 포스팅에서 깊게 다뤄보겠습니다.
마무리
Bloc
과 Provider
에 비해 GetX
는 정말 쉽게 사용할 수 있어서 회사 프로젝트에서도 적극적으로 도입했었습니다. 아주 간단하게 "변할 수 있는 데이터면 Rx 객체로 선언하고 그 데이터를 Obx 로 감싸기만 하면 된다"만 가르쳐줘도 처음 써보는 신입분들이 30분이면 익숙해졌습니다. 라우트 관리와 페이지 상태 관리도 정말 많이 지원하고 있어 기회가 된다면 관련 내용 정리해보겠습니다.
Author And Source
이 문제에 관하여([Flutter] GetX 와 UI 업데이트), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@someh/Flutter-GetX-와-UI-업데이트저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)