Flutter에서 상태를 관리하기 위해서 Bloc패턴이나 Provider와 같은 패키지를 사용하게 된다. 그러나 시간이 흘러 GetX가 나와 사람들이 많이 쓰는 추세이다.
GetX
GetX설치와 관련해서는 따로 정리해놓은 글이 있기 때문에 이를 첨부해놓겠다.
2023.02.24 - [Flutter] - [GetX] getX 사용해서 snackbar 구현
상태 관리
내 경우에는 GetX없이 부모 위젯과 자식 위젯간의 데이터 전달을 해주려고 했는데, 잘 안되서 이를 사용하게 되었다.
GetX는 다음과 같이 두가지 상태 관리 방법이 존재한다.
- 단순 상태 관리(Simple state management)
- 반응형 상태 관리(Responsive state management)
단순 상태 관리
GetX를 사용하여 단순 상태 관리를 위해, lib폴더에서 controller폴더를 하나 생성한다. 그리고, count_controller.dart 파일을 생성한다.
import 'package:get/get.dart';
class CountController extends GetxController {
int count = 0;
void increment() {
count++;
update();
}
}
GetX에서 상태 관리를 위한 클래스를 생성할 때에는 GetxController를 상속받게 된다.
- count : 관리할 상태 변수를 선언한다.
- increment : 해당 변수를 업데이트할 함수를 선언한다.
- update : 단순 상태 관리를 사용하는 경우, update() 함수를 사용하여 상태가 변경되었음을 알려준다. update()를 사용하지 않으면, 상태값은 변경이되지만 화면 갱신이 일어나지 않는다.
import 'package:get/get.dart'; //1
import 'controller/count_controller.dart';
...
class MyHomePage extends StatelessWidget {
final String title;
const MyHomePage({Key? key, required this.title}) : super(key: key);
@override
Widget build(BuildContext context) {
final controller = Get.put(CountController()); //2
return 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:',
),
GetBuilder<CountController>(builder: (controller) {//3
return Text(
'${controller.count}', //4
style: Theme.of(context).textTheme.headline4,
);
}),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: controller.increment, //5
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
위의 코드에 부여한 숫자 순서대로 설명을 기입하였다.
- import : getX와 controller를 사용하기 위하여 임포트해온다.
- controller : controller에 선언한 값들을 사용하기 위하여 이를 변수로 선언한다.
- Get.put() : Get.put()안에 controller를 넣어주면 여기에 넣어준 controller를 사용하겠다는 말이다.
- GetBuilder : 단순 상태 관리에서 상태의 변화를 감지하고 변경된 상태값을 적용하기 위해서는 **GetBuilder를 사용**해야 한다. 그렇지 않으면 상태가 변경된 것을 화면에서 알지 못한다.
- count : controller.count는 controller안에 선언해주었던 count값을 가져오는 것을 말한다.
- increment : floatingactionbutton을 클릭시 controller의 increment함수를 호출하여 사용할 수 있도록 이벤트를 연결하였다.
→ 여기서 GetX로 상태관리를 해주었음으로 위에서 StatefulWidget을 사용할 필요가 없다. StatelessWidget으로 수정해줘도 된다.
반응형 상태 관리
반응형 상태 관리는 단순 상태 관리와는 달리 update함수를 사용하지 않고, 내부 로직으로 값의 상태 변화를 감지하고 화면에 변경된 값을 적용한다.
lib폴더에서 controller폴더를 하나 생성하여, IndexController.dart 파일을 생성한다.
import 'package:get/get.dart';
class IndexController extends GetxController {
final selectedIndex = 0.obs;
void onItemTapped(int index) {
selectedIndex.value = index;
print(index);
}
}
- selectedIndex : 관리할 상태 변수를 말한다.
- onItemTapped : 해당 변수를 업데이트할 함수를 선언한다.
- 여기서 selectedIndex.value는 위에서 선언한 상태변수의 값을 가져오기 위해 value를 붙인 것이다.
→ 단순 상태 관리와는 다르게 상태변수를 선언할 때, .obs(관찰 연산자)를 붙여준다. 이렇게 생성하는 것은 반응형 상태변수로 사용하기 위함이다.
import 'package:flutter/material.dart';
import 'package:todo/main.dart';
import 'package:get/get.dart';
import 'package:todo/controller/IndexController.dart'; //1
class BottomNavi extends StatefulWidget {
const BottomNavi({
super.key,
});
@override
BottomNaviState createState() => BottomNaviState();
}
class BottomNaviState extends State<BottomNavi> {
@override
Widget build(BuildContext context) {
final controller = Get.put(IndexController()); //2
return Obx( //3
() => BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
backgroundColor: Colors.red,
),
BottomNavigationBarItem(
icon: Icon(Icons.calendar_month_outlined),
label: '캘린더',
backgroundColor: Colors.green,
),
],
currentIndex: controller.selectedIndex.value, //3
selectedItemColor: Colors.blue,
onTap: controller.onItemTapped), //4
);
}
}
위의 코드에 부여한 숫자 순서대로 설명을 기입하였다.
- import : getX와 controller를 사용하기 위하여 임포트해온다.
- controller : controller에 선언한 값들을 사용하기 위하여 이를 변수로 선언한다.
- Get.put() : Get.put()안에 controller를 넣어주면 여기에 넣어준 controller를 사용하겠다는 말이다.
- Obx : 여기에서 단순 상태관리와는 다르게 Obx를 사용하여 상태의 변경을 감지한다.
- selectedIndex : controller안에 선언해주었던 selectedIndex값을 가져온다.
- onItemTapped : BottomNavigationBar를 클릭시 controller의 onItemTapped함수를 호출하여 index를 변경하였다.
차이점
단순 상태관리는 설정한 값이 변하든 변하지 않든 무조건 호출이 된다. 하지만 반응형 상태관리는 값이 변해야 호출이 이루어진다.
예를 들어, value를 5로 설정해주는 method를 만들었을 때,
단순 상태관리는 method를 실행시킬 때마다 무조건 호출이 이루어지는 반면, 반응형 상태관리는 method를 실행시켜도 값이 변하지 않는다면(즉, value값이 이미 5인데도 버튼을 계속 누른다면) 재호출은 이루어지지 않는다.
🔗 참고
https://dev-yakuza.posstree.com/ko/flutter/getx/state/#단순-상태-관리