Flutter_GetX_Study_repo
GetX를 사용하기 위한 기초적인 내용을 담고있는 레포입니다.
dependencies: get: ^4.1.4
flutter pub get
import 'package:get/get.dart';
// 변경 전
MaterialApp(
title: 'Getx example',
home: HomePage(),
)
// 변경 후
GetMaterialApp(
title: 'Getx example',
home: HomePage(),
)
새로운 화면으로 이동한다. 아래의 코드에서는 NextPage()로 이동한다.
Get.to(NextPage());
미리 설정해둔 이름을 통해 새로운 화면으로 이동한다. 아래의 코드에서는 /next
라는 이름을 가진 페이지로 이동
GetMaterialApp(
title: 'Getx example',
home: HomePage(),
getPages: [
GetPage(name: '/next', page: () => NextPage()),
],
)
Get.toNamed('/next');
이전 화면으로 돌아간다.
Get.back();
다음 화면으로 이동하면서 이전 화면을 아예 없애버린다. 이전 화면으로 돌아갈 필요가 없을 때 사용한다.
Get.off(NextPage());
NextPage()에서 버튼을 클릭해도 HomePage()가 없어졌기 때문에 돌아갈 수 없다.
***Get.off()
가 이전 화면 하나만 없앴다면 Get.offAll()
는 이전의 모든 화면을 없애고 다음 화면으로 이동한다.***
Get.offAll(NextPage());
기본적으로 Snackbar는 하단에서만 나온다. 그런데 GetX를 사용하면 Snackbar를 상단에 보이게 할 수도 있다.
제목과 메시지를 설정하면 해당 내용으로 Snackbar를 보여준다. 지속시간(duration
), 방향(snackPosition
), 배경색(backgroundColor
) 등 여러 설정들을 추가할 수 있다.
Get.snackbar('Snackbar', 'Snackbar', snackPosition: SnackPosition.TOP);
***Get.snackbar()
와 거의 동일하다. Get.showSnackbar()
만의 특별한 용도가 있는지는 모르겠다.***
Get.showSnackbar(
GetBar(
title: 'Snackbar',
message: 'Snackbar',
duration: Duration(seconds: 2),
snackPosition: SnackPosition.BOTTOM,
),
);
※ 기본 디자인임
Dialog를 화면에 띄어준다. 확인/취소 시에 실행할 함수(onConfirm
, onCancel
), 확인/취소 텍스트(textConfirm
, textCancel
), 배경색(backgroundColor
) 등 여러 설정들을 추가할 수 있다.
Get.defaultDialog(title: 'Dialog', middleText: 'Dialog');
제목과 텍스트만 설정했지만, 디자인 및 설정들이 기본적으로 되어있는 것을 볼 수 있다.
***Get.defaultDialog()
와 달리 원래 사용하던 기존Dialog
위젯을 가져와서 사용할 수 있다.***
Get.dialog(
Dialog(
child: Container(
height: 100,
child: Center(
child: Text('Dialog'),
),
),
),
);
내부에 들어갈 위젯만 넣어주면 해당 위젯을 포함하는 BottomSheet를 보여준다.
Get.bottomSheet(
Container(
height: 100,
color: Colors.white,
child: Center(
child: Text('BottomSheet'),
),
),
)
GetX에는 크게 두가지의 상태 관리법이 존재한다.
첫번째 방식은 비교적 간단한(simple) 방식이다. 이 방식은 이후에 설명할 reactive 방식보다 메모리를 적게 사용한다는 장점이 있다.
***GetxController
를 extend하는 Controller
클래스를 선언하고, 초기값을 0으로 설정한 count1
변수를 선언한다.***
class Controller extends GetxController {
var count1 = 0;
}
***GetBuilder
을 통해 화면에 count1
변수를 보여준다. 이때 init
을 설정하지 않으면 에러가 발생하는 것을 유의하자.***
GetBuilder<Controller>(
init: Controller(),
builder: (_) => Text(
'clicks: ${_.count1}',
),
)
이제 count1
변수를 증가시켜야 한다. 또한 증가할 때 이를 화면에 알려줘야한다. 이를 위해 update()
함수를 사용한다.
class Controller extends GetxController {
var count1 = 0;
void increment1() {
count1++;
update();
}
}
Get.find(), Get.put()는 순서상 여기에 들어가는 것이 매끄러워서 넣은 것이지, simple 방식에 해당하는 것은 아니다. 두 방식(simple, reactive) 모두에서 사용된다.
Get.find()
을 사용하여 increment1()
을 호출하는 버튼을 만들어 텍스트 아래에 배치한다.
TextButton(onPressed: Get.find<Controller>().increment1, child: Text('increment1'))
하지만 리빌드해보면 Get.find<Controller>()
에서 에러가 발생할 것이다.
이는 Get.find<Controller>()
가 Controller
를 찾는 시점이 GetBuilder()
의 init
에서 Controller
를 등록하기 이전이라 그렇다.
이 문제를 해결하기 위해서 Get.put()
을 사용한다.
우선 build()
메소드 내부에 controller
변수를 선언하며, 이때 Get.put()
를 통해 Controller
를 등록한다.
build(BuildContext context) {
final controller = Get.put(Controller());
// ...
}
Widget
controller
변수를 선언하면서 Controller
를 등록했기 때문에 GetBuilder
에서 또 등록할 필요가 없다. 따라서 init
부분을 지운다.
GetBuilder<Controller>(
// init 부분 삭제.
builder: (_) => Text(
'clicks: ${_.count1}',
),
)
버튼에서 increment1()
를 호출할 때, Get.find()
대신 controller
변수를 사용한다.
TextButton(onPressed: controller.increment1, child: Text('increment1')),
simple 방식은 메모리를 적게 사용한다는 장점이 있었다. 그렇다면 reactive 방식은 무슨 장점이 있고 어느 경우에 사용할까?
reactive 방식에는 simple 방식에는 없는 특별한 기능이 있다. 이에 대해선 reactive 방식에 대한 기본 설명 이후에 정리해보도록 하겠다.
reactive 방식에서는 observable 변수라는 특별한 변수를 사용한다. observable 변수를 Rx라고도 부른다. 이런 Rx를 선언하는 방법에는 아래와 같이 3가지가 있다.
Value.obs
Rx<Type>(Value)
RxType(Value)
이 중 가장 간단한 1번 방법을 주로 사용한다.
우리도 1번 방법을 사용하여 count2
변수를 정의해보자.
var count2 = 0.obs; // 1번
var count2 = Rx<int>(0); // 2번
var count2 = RxInt(0); // 3번
Rx의 값을 접근할 때는 일반적인 변수의 값의 경우와 다르게 .value
를 통해 접근할 수 있다. 여기서 주의해야할 점이 있다. String
과 int
같은 primitive type에는 .value
를 사용해야하지만, List
에서는 .value
가 필요없다. dart api가 리스트에서만 .value
없이도 값에 접근할 수 있게 해주기 때문이다.
이 점은 좀 불편하다고 생각했다. .value
를 붙이는 것은 더 길게 써야하는 것이고, 그 방법 마저도 List
라는 예외가 존재하기 때문이다. 이 이유에 대해서 찾아보니, code generator와 decoration을 사용하면 이 불편함을 해결할 수 있지만, 외부 종속성을 없애고자 그대로 두었다고 한다.
void increment2() => count2.value++;
.value
를 사용해서 count2
의 값을 1 증가시키는 increment2()
함수를 정의했다. reactive 방식에선 update()
함수가 필요하지 않다.
simple 방식의 GetBuilder
과 같은 역할을 하는 것이 GetX
이다. 그럼 GetX
를 사용해서 count2
의 값을 보여주는 텍스트를 만들어보자.
GetX<Controller>(
builder: (_) => Text(
'clicks: ${_.count2.value}',
),
),
Get.put(),
init
부분 simple 방식과 똑같다.
필요한 경우에는 GetBuilder
에서처럼 init
을 통해 Controller
를 등록할 수 있다.
GetX
보다 더 간단한 방법이 있다. 바로 Obx()
를 사용하는 것이다. Obx()
의 경우 사용할 컨트롤러의 종류를 따로 명시할 필요가 없고, 보여줄 위젯만 리턴하면 된다.
하지만 이 방법은 무조건 Get.put()
을 필요로 한다.
Obx
를 사용해서 count2
의 값을 보여주는 텍스트를 만들어서 GetX
를 통해 만든 텍스트 하단에 배치하자.
Obx(() {
return Text(
'clicks: ${controller.count2.value}',
);
}),
이미 앞선 예시에서 Get.put()
을 통해 선언한 controller
가 존재하기 때문에 이를 바로 사용했다.
이전에 말했던 reactive 방식에서만 사용할 수 있는 특별한 기능들이 바로 Workers이다. Workers를 사용하면 Rx들의 변화를 감지하고 다양한 상황 별로 적절한 대응을 하도록 구현할 수 있다.
Workers에는 아래와 같이 총 4가지가 있다.
// count2가 처음으로 변경되었을 때만 호출된다.
once(count2, (_) {
print('$_이 처음으로 변경되었습니다.');
});
// count2가 변경될 때마다 호출된다.
ever(count2, (_) {
print('$_이 변경되었습니다.');
});
// count2가 변경되다가 마지막 변경 후, 1초간 변경이 없을 때 호출된다.
debounce(
count2,
(_) {
print('$_가 마지막으로 변경된 이후, 1초간 변경이 없습니다.');
},
time: Duration(seconds: 1),
);
// count2가 변경되고 있는 동안, 1초마다 호출된다.
interval(
count2,
(_) {
print('$_가 변경되는 중입니다.(1초마다 호출)');
},
time: Duration(seconds: 1),
);
이 4가지의 Workers를 Controller
에 적용해보자.
void onInit() {
super.onInit();
once(count2, (_) {
print('$_이 처음으로 변경되었습니다.');
});
ever(count2, (_) {
print('$_이 변경되었습니다.');
});
debounce(
count2,
(_) {
print('$_가 마지막으로 변경된 이후, 1초간 변경이 없습니다.');
},
time: Duration(seconds: 1),
);
interval(
count2,
(_) {
print('$_가 변경되는 중입니다.(1초마다 호출)');
},
time: Duration(seconds: 1),
);
}
Controller
에 onInit()
override
하고, super.onInit()
을 제일 먼저 호출한다. 그 다음 사용하고자 하는 Worker를 등록해주면 된다.
https://terry1213.github.io/flutter/flutter-getx/#22-reactive-%EB%B0%A9%EC%8B%9D
- 위의 글을 토대로 만들었으며 최소한의 내용만을 담으려고 글을 작성했습니다.
좀 더 자세히 알고싶으신 분들은 위의 글을 참고해주시기 바랍니다!!
- GetView를 통한 코드 가독성 챙기기
엄청 정리가 잘 되어 있네요. 많은 도움이 되었습니다. 감사합니다.