GetX
Updated:
GetX 특징
-
context
없이routing
이 관리됩니다.Get.to(() => SomePage())
-
일반적으로 dispose 관리를 해야합니다. getX 는 기본적으로 dispose 수행되고, 남기고 싶을때만 명시적으로 남기겠다는 코드를 넣습니다.
-
business logic 과 view 를 분리할 수 있습니다. (binding 이용)
GetX 사용
- GetX package 를 설치하고,
MaterialApp
을GetMaterialApp
으로 바꿔줘야 GetX 에 있는 기능들을 다 사용할 수 있습니다.
GetxController
-
controller 는 business logic 이 위치합니다. (데이터를 저장하고 가공하는 역활)
-
view 에서 이를 쉽게 가져다 쓸 수 있습니다.
-
dispose 를 따로 해주지 않아도 navigation stack 에서 빠질때 자동으로 dispose 됩니다.
-
onInit()
: initState() 역활을 함 -
onReady()
: widget 이 스크린에 다 그련진 후에 사용하는 method -
onClose()
: dispose() 역활을 함
// in controller.dart
class Controller extends GetxController {
int counter = 0;
void increment() {
counter++;
update(); // 상태가 변한것을 update 하는것
}
}
GetBuilder
GetxController 의 저장된 data 를 view 단계에서 쓰이는 방식 중 하나임
GetBuilder<Controller>(
init: Controller(), // app 의 어디서든 최초 1회만 호출하면 됨
builder: (value) => Text(
'${value.counter}'
),
),
GetBuilder<Controller> (
builder: (value) => Text(
'${value.counter}'
),
),
-
GetBuilder 는 stateFull widget 을 대신해서 사용할 수 있습니다.
-
빠르고, 메모리 비용이 저렴합니다
-
unique id 를 줘서 구분 할 수 있습니다.
GetBuilder<Controller>(
id: 'first', // getBuilder 를 id 로 구분함
init: Controller(),
builder: (value) => Text(
'${value.counter}'
),
),
GetBuilder<Controller> (
id: 'second',
init: Controller(),
builder: (value) => Text(
'${value.counter}'
),
),
// in controller.dart
class Controller extends GetxController {
int counter = 0;
void increment() {
counter++;
update(['first']); // id 값을 parameter 로 설정하면 해당 id를 가진 getbuilder 만 update 됩니다
}
}
- 단점으로는 reactive 하지 않다는것임. (명시적으로 계속 갱신을 시켜줘야 작동한다는 것임) - 값이 변경 될때 마다, update() 을 호출해줘야 합니다
GetX
-
stream 방식으로 streamBuilder 와 비슷합니다
-
RxInt, RxString 등으로 변수를 사용합니다
-
모든 class 객채도 사용 가능 합니다. myClass(). obs 형태로 선언
class Controller extends GetxController {
RxInt counter = 0.obs; // Rxint 타입으로 변수 선언 .obs 을 붙이면서 변수가 변화되는것을 감지하는 기능
void increment() {
counter.value++;
}
}
GetX<Controller>(
init: Controller(),
builder: (val) => Text(
'${val.counter.value}' // counter 의 변화를 바로바로 반영해야 되기 때문에 .value 라고 접근해야 됨
),
),
Obx
-
사용 문법이 가장 단순
-
GetX 는 get.find 를 통해 사용하던 instance 를 찾아서 같이 공유해서 사용할 수 있습니다.
// model
class User {
String? name;
// constructure 생성
User({this.name});
}
// Controller
class Controller extends GetxController {
// instance 생성
var user = User(name: "Jacob").obs; // 사용자 정의 User 클래스 생성
// method (name chage)
void chageName() => user.value.name = "Emma"; // value 로 접근해서 name 변수 변경
}
// View
Obx(() => Text( // Obx 로 감싸주면 끝, user 변화 catch 및 적용
'${controller.user.value.name}'
),
),
// 다른 page에서 instance
class pageOne extends StatelessWidget {
Controller controller = Get.put(Controller());
// controller binding 필요함
}
// 다른 widget 에서 생성된 controller instance 그대로 가져다가 access 하기
class PageSeven extends StatelessWidget {
Controller controller = Get.find(); // controller 접근하기
}
GetBuilder vs GetX, Obx 비교
-
GetBuilder : 가장 빠름, stream 사용안함, State를 builder 들간에 공유함. ram 절약 됨
-
GetX : value 가 실제로 바뀌었을때만 redraw 함. controller 를 instance 화 하지 않음. reactive 함
-
Obx : 문법이 제일 심플하고, 하나의 위젯에서 여러개의 controller 사용이 가능, binding 이 편함
Dependency injection
- 하나의 instance 를 다른 instance 에 할당하는 방법을 말합니다
// 일반적인 dependency injection 예시
class HomePage extends StatelessWidget {
Controller controller; // Controller type 의 변수를 생성
HomePage({this.controller}); // contructor 생성
}
class OtherPage extends StatelessWidget {
const OtherPage({Key? key}) : super(key: key);
Controller someController = Controller(); // instance 생성
@override
Widget build(BuildContext context) {
return Container(
child: HomePage(
controller: someController,
));
}
}
- GetX 에서는 Get.put 과 Get.find 를 이용합니다
class Homepage extends StatelessWidget {
// Gex Controller instance 생성 Get.put 사용 (정의하기)
Controller controller = Get.put(Controller());
}
class SecondPage extends StatelessWidget {
Controller controller =
Get.find(); // 기존에 생상된 controller instance 를 찾아서 가져와서 사용함 (가져오기)
}
Bindings
-
Bindings 를 상속하고, dependencies 를 override 합니다
-
Bindings 를 통해 View와 control 코드를 좀 더 분리해서 사용이 가능합니다
-
Bindings 는 dependencies 를 정의하고 이를 route 에 연결합니다
-
이를 활용하기 위해서는 꼭 GetX route 시스템을 사용해야 합니다
-
controller 를 route 에 따라 관리 할 수 있기 때문에 편리 합니다. 페이지에 필요한 컨트롤러를 바인인하여 전달하면 페이지가 생성성되면서 바로 인스턴스가 선언되어 사용 가능한 상태가 되고 페이지에서 빠져 나오면 곧바로 해당 페이지에서 등록되어 사용되었던 인스턴스(controller) 가 자동으로 dispose 처리 됩니다
class HomeBiding implements Bindings {
// extends: 부모에서 선언/정의를 모두 하며 자식은 메소드/변수를 그대로 사용할 수 있음
// implements (interface 구현): 부모 객체는 선언만 하며 정의(내용)은 자식에서 오버라이딩 해야됨
// abstract: extends 와 interface 혼합, extends 하되 몇개는 추상 메소드로 구현되었음
@override
void dependencies() {
// TODO: implement dependencies
Get.put<Controller1>(Controller1());
Get.put<Controller2>(Controller2());
}
}
// 위의 정의된 dependency 를 route 에 binding
GetMaterialApp (
initialRoute: "/",
getpages: [
GetPage(name: "/", page: () => HomePage(), binding: HomeBiding(),),
],
);
Get.to(HomeBiding(), binding: HomeBiding(),);
Get.toNamed("/", binding: HomeBindings(),);
GetMaterialApp (
initialRoute: "/",
// app 시작과 동시에 dependencies 를 만들 수 있다
initialBinding: HomeBinding(),
);
GetMaterialApp (
initialRoute: "/",
// Bindings clsss 를 만들지 않고 바로 controller 를 binding 할 수 있다
initialBinding: BindingsBuilder(() => {Get.put(Controller1())}),
);
class HomePage extends StatelessWidget {
Controller1 controller = Get.find(); // Get.find() 를 통해 controller 를 view 에서 사용 가능함
}
Bindings 를 사용해야 되는 이유?
binding 을 사용하지 않아도 get.put 과 get.find 로 사용하면 되는데 만약 controller 가 10개 이상되고 그 이상 많게 되면 view 단계 page 에서 controller 를 매번 controller 개 만큼 find 해줘야 되서 코드가 길어지고 복잡해지는데 binding 을 통해 route 경로에 묶게 되면 clean code 가 됩니다
Get.put
-
controller 를 정의하는 명령어 임: view page 에서 instance 생성해서 controller 에 접근하는것입니다
-
Get.put 은 기본적으로 route 가 살아 있을 경우에만 memory 에 남아 있게 됩니다. 즉, 페이지에서 벗어나면 자동으로
dispose()
되는데,permanent: true
설정을하면 페이지를 벗어나도 instance 는 사라지지 않고 메모리에 남아 있게 됩니다
class HomePage extends StatelessWidget {
// controller 정의 : controller instance 생성
Controller controller = Get.put(Controller());
@override
Widget build(BuildContext context) {
return Text(controller.name); // controller 에 저장되어 있는 data 표시
}
}
class HomePage2 extends StatelessWidget {
// tag 속성을 부여해서 같은 Controller 에서 각각 다른 변수로 사용 할 수 있음
Controller controller1 = Get.put(Controller(), tag: 'ATag');
Controller controller2 = Get.put(Controller(), tag: 'BTag');
// permanent true 되면 페이지 벗어나도 instance 계속 남아 있게 됨
Controller controller3 = Get.put(Controller(), tag: 'CTag', permanent: true);
// ....
}
class SecondPage extends StatelessWidget {
// get.find 에서 tag 로 각각 다른 객체를 불러 올 수 있음
Controller controller1 = Get.find(tag: 'ATag');
Controller controller2 = Get.find(tag: 'BTag');
// ....
}
Get.lazyPut
-
간단히 나중에 메모리에 올리겠다라는 명령어 인데, Binding 에서 선언할때 메모리로 올라 오는것이 아니라, get.find 로 호출 될때 get.put 이 그때 메모리에 올라가는것입니다
-
lazyPut 에
fenix: true
의 값을 주게 되면 다시 생성될때 re-initialize 됩니다
class HomeBiding implements Bindings {
@override
void dependencies() {
// TODO: implement dependencies
Get.lazyput<Controller>(() => Controller());
Get.lazyput<Controller>(() => Controller(), tag: 'tagged!');
}
}
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Text(Get.find<Controller>().name);
}
}
Get.putAsync
- 비동기 방식으로 put 을 사용한다는것인데, db 를 연결할때, http 를 불러오는것이 controller 안에 있을 경우 사용합니다. 먼저 요청을하고 비동기로 다른 작업을 먼저 처리 한다음에 get.find 되면 그때 get.put 하는것입니다
Get.create
- Get.find 가 불릴때마다 instance 를 만듭니다. 즉, GetX 를 사용하는것은 생성된 instance 공유해서 를 get.find 로 찾아서 여러 페이지에서 사용하는 것인데, 만약,
ListView.builder
같이 listView 를 만들때 return 값으로 Widget 을 looping 될때 Get.create 로 만들게되면 looping 할때 마다 controller instance 를 생성해서 각각의 변수를 만들어서 사용할 수 있습니다.
GetView
-
controller 를 조금더 편하게 만들수 있는 기능입니다. 만약 page 에 Controller getter 를 제공 합니다.
-
하나의 Controller 만 사용한다면 GetView 가 좋은 옵션입니다. 왜냐하면 get.find 가 필요 없어도 data 값을 불러 옵니다. (get.find 가 필요가 없음)
class HomePage extends GetView<Controller> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Row(
// get.find 없이도 GetView 안에서 자동으로 instance 가 생성되어 한개의 controller 를 가져올때 자동으로 controller 라는 변수에 접근해서 data 를 가져 옵니다
children: [
Obx(() => Text('controller.total.value')),
],
),
),
}
}
GetWidget
- GetView 와 비슷한데, 다른점은 controller 를 사용할때 get.find 가 자동 수행 됩니다 (최초 1회만) 그래서 get.create 과 같이 사용하면 좋습니다
Provider 와 같이 가장 많이 사용되는 상태관리 툴로써 GetX 는 크게 2가지 기능으로 나뉠 수 있습니다
-
Navigation
-
State Management
Navigation
1.페이지 이동하기
ElevatedButton(
onPressed: () {
// 원래 material page 를 사용해야 함
// Navigator.of(context).push(
// MaterialPageRoute(
// builder: (_) => ScreenTwo(),
// )
// );
// GetX를 사용해서 페이지 이동
Get.to(() => ScreenTwo());
},
child: Text(
"Screen 2 이동",
style: TextStyle(fontSize: 20),
),
2.페이지 뒤로가기
ElevatedButton(
onPressed: () {
// 원래 뒤로 가기 기능 : pop 할때 뒤로갈 페이지가 있어야지 pop 을 하는데 안그려면 materialApp 을 완전히 나가버려서 black page 로 감
// if(Navigator.of(context).canPop()){
// Navigator.of(context).pop();
// }
// GetX 뒤로가기 : stack 을 하나 지우면서 pop 을 해야됨
Get.back();
},
child: Text(
'뒤로가기',
style: TextStyle(fontSize: 20),
),
),
3.홈페이지로 바로가는 버튼
Get.off
을 사용하면 home 으로 바로 갈 수 있는 버튼 을 만드는것
ElevatedButton(
onPressed: () {
// 원래는 pushReplacement 사용해서 ScreenTwo() 로 넘어가면 뒤로가기 안되게 함
// Navigator.of(context).pushReplacement(
// MaterialPageRoute(
// builder: (_) => ScreenTwo(),
// ),
// );
// Get.off 를 사용하면 쌓여 있는 stack 이 지워지면서 home 화면으로 감
Get.off(() => ScreenTwo());
},
child: Text(
"전 페이지로 돌아가지 못하게하기",
style: TextStyle(fontSize: 20),
),
),
4.모든 페이지 스택 삭제하기
- splash , login screen 을 만들 때, 어떠한 페이지를 띄우고서 바왔던 모든 page 들을 navigation stack 에서 삭제 시키는 것임
ElevatedButton(
onPressed: () {
// 모든 페이지를 삭제하고, 새로운 page 를 push 해주는것 pushAndRemoveUntil 을 사용하게 됨
// Navigator.of(context).pushAndRemoveUntil(
// MaterialPageRoute(
// builder: (_) => ScreenTwo(),
// ),
// (route) => false,
// );
// Get.offAll 을 사용해서 뒤로가기 버튼을 눌러도 stack 이 다 지워지기 때문에 뒤로 갈수가 없게 됨
Get.offAll(() => ScreenTwo());
},
child: Text(
"모든 페이지 스택 삭제하기",
style: TextStyle(fontSize: 20),
),
),
5.리턴값 받아오기
ScreenThree 에서 선택된 값 받아오기
// in navigation.dart
int returnVal = 0;
Text(
'리턴값 : $returnVal',
),
ElevatedButton(
onPressed: () async {
// 받아온 값을 비동기로 resp 에 변수 선언함
final resp = await Get.to(() => ScreenThree());
// state 변경
setState(() {
returnVal = resp;
});
},
child: Text(
'리턴값 받아오기',
style: TextStyle(fontSize: 20),
),
),
// in screen_three.dart
int radioVal = 0;
@override
Widget build(BuildContext context) {
return DefaultAppbarLayout(
title: 'Screen Three',
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
children: [
RadioListTile(
title: Text('0'),
groupValue: radioVal,
value: 0,
onChanged: (int? value) {
setState(() {
radioVal = value!;
});
},
),
RadioListTile(
title: Text('1'),
groupValue: radioVal,
value: 1,
onChanged: (int? value) {
setState(() {
radioVal = value!;
});
},
),
RadioListTile(
title: Text('2'),
groupValue: radioVal,
value: 2,
onChanged: (int? value) {
setState(() {
radioVal = value!;
});
},
),
],
),
ElevatedButton(
onPressed: () {
// Get.back 하면서 result: radioVal 값을 전달 하기
// 뒤로가기 기능
Get.back(result: radioVal);
},
child: Text(
'뒤로가기',
style: TextStyle(fontSize: 20),
),
),
],
),
),
);
}
6.argument 값 보내기
위의 return 값을 받아오는 거와 반대로 정해진 argument 값도 다른 페이지에 전달할 수 있습니다 (Screen Four 로 보내기)
// in navigation.dart
ElevatedButton(
onPressed: () {
Get.to(() => ScreenFour(), arguments: 'GetX 값 보내기 test');
},
child: Text(
'argument 보내기',
style: TextStyle(fontSize: 20),
),
),
// in Screen four
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
Get.arguments,
style: TextStyle(fontSize: 20),
),
ElevatedButton(
onPressed: () {
Get.back();
},
child: Text(
'뒤로가기',
style: TextStyle(fontSize: 20),
),
),
],
),
7.Transition
GetX 에서 제공하는 많은 page transition 을 적용하면 좀 더 다이나믹 하게 페이지 전환을 할 수 있습니다.
- GetX 에서 제공하는 transition 속성은 다음과 같습니다
enum Transition {
fade,
fadeIn,
rightToLeft,
leftToRight,
upToDown,
downToUp,
rightToLeftWithFade,
leftToRightWithFade,
zoom,
topLevel,
noTransition,
cupertino,
cupertinoDialog,
size,
native
}
ElevatedButton(
onPressed: () {
// GetX를 사용해서 페이지 이동
Get.to(() => ScreenTwo(),
transition: Transition.rightToLeftWithFade);
},
child: Text(
"Transition",
style: TextStyle(fontSize: 20),
),
),
8.Named Route
-
GetX 의 Navigation 에서 유용한 기능으로 Material App 에서 on generic route 를 사용해서 named route 를 사용 가능한데, GetX 에서는
getPages
를 사용해서 url 에 파라미터를 집어 넣는 기능을 간단히 만들 수 있습니다. -
Web 에서 routing 할때, parameter 와 query 를 사용해서 자주 사용하는데 on generic routing 을 사용하게 되면 구현이 복잡하지만 GetX 에서는 간단히 사용할 수 있습니다.
// in main.dart
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: 'Flutter GetX',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
getPages: [
GetPage(
name: '/nav',
page: () => Navigation(),
),
GetPage(
name: '/two',
page: () => ScreenTwo(),
),
GetPage(
name: '/three',
page: () => ScreenThree(),
),
GetPage(
name: '/four',
page: () => ScreenFour(),
),
// named route 를 위한 :param 을 사용함
GetPage(
name: '/five/:param',
page: () => ScreenFive(),
),
],
);
}
}
// navigation.dart
ElevatedButton(
onPressed: () {
// five/:param?id=444&name=Jacob 페이지로 named route 함
Get.toNamed('/five/1234?id=444&name=Jacob');
},
child: Text(
"Named route",
style: TextStyle(fontSize: 20),
),
),
// screen_five.dart
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
Get.parameters['param']!,
style: TextStyle(fontSize: 20),
),
Text(
Get.parameters['id']!,
style: TextStyle(fontSize: 20),
),
Text(
Get.parameters['name']!,
style: TextStyle(fontSize: 20),
),
],
),
9.Snack bar 기능
- material App 의 snack bar 의 기능을 GetX 에서 snack bar의 기능을 지원합니다
ElevatedButton(
onPressed: () {
Get.snackbar(
'제목을 써주세요',
'내용을 여기에 적으시면 됩니다',
snackPosition: SnackPosition.BOTTOM,
);
},
child: Text(
"SnackBar",
style: TextStyle(fontSize: 20),
),
),
10.Dialog 기능
- GetX 를 사용하면 쉽게 다이얼 로그 (alert 창)을 쉽게 만들 수 있습니다. option 이 많기 때문에 customizing 을 쉽게 할 수 있습니다
ElevatedButton(
onPressed: () {
Get.defaultDialog(
title: 'Dialog 제목',
middleText: 'Dialog 내용',
);
},
child: Text(
"Dialog",
style: TextStyle(fontSize: 20),
),
),
11.Bottom Sheet
- 화면 하단에 listView 라던지 나타내고 싶은 Widget 을 넣으면 아래에서 부터 화면에 표시하기 됩니다
ElevatedButton(
onPressed: () {
Get.bottomSheet(
Container(
color: Colors.white,
child: Wrap(
children: <Widget>[
ListTile(
leading: Icon(Icons.music_note),
title: Text('Music'),
onTap: () => {}),
ListTile(
leading: Icon(Icons.videocam),
title: Text('Video'),
onTap: () => {},
),
],
),
),
);
},
child: Text(
"Bottom Sheet",
style: TextStyle(fontSize: 20),
),
),
State Management
1.on Update
- 왠만한 상황에서는 on update 기능을 사용하는데, 왜냐하면 메모리 사용양이 적게 됨
// in getx_controller.dart
// Getx controller class 생성
class BuilderController extends GetxController {
int count = 0;
// increse method 생성
increment() {
count++;
// state 가 변경될때 update() 호출해서 변경된것 알림
update();
}
}
// in on_update_screen.dart
class _OnUpdateScreenState extends State<OnUpdateScreen> {
@override
Widget build(BuildContext context) {
// controller 변수에 Get.put 하면 initialize 해서 사용할 수 있음
final controller = Get.put(BuilderController());
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'On Update',
style: TextStyle(
fontSize: 20,
),
),
GetBuilder<BuilderController>(
builder: (_) {
return Text(
'count : ${_.count}',
style: TextStyle(
fontSize: 20,
),
);
},
),
ElevatedButton(
onPressed: () {
controller.increment();
},
child: Text(
'Count 업!',
style: TextStyle(
fontSize: 20,
),
),
),
],
),
2.Reactive
// in getx_controller.dart
class ReactiveController extends GetxController {
// reactive 하게 변수 생성만들기
RxInt count1 = 0.obs;
var count2 = 0.obs;
class _ReactiveScreenState extends State<ReactiveScreen> {
final controller = Get.put(ReactiveController());
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Reactive',
style: TextStyle(
fontSize: 20,
),
),
// Reactive 로 GetX 불러오기
GetX<ReactiveController>(
builder: (_) {
return Text(
'Count 1: ${_.count1.value}',
style: TextStyle(
fontSize: 20,
),
);
},
),
ElevatedButton(
onPressed: () {
controller.count1++;
},
child: Text(
'Count1 UP!',
style: TextStyle(
fontSize: 20,
),
),
),
],
),
Obx 을 사용
- Obx 를 사용하면 builder 를 생성하지 않고 Controller 에 선언된 변수에 접근해서 사용할 수 있음 (Observable 의 값을 불러올때 사용함)
// reactive.dart
Obx(() {
return Text(
'Count 2 : ${controller.count2.value}',
style: TextStyle(
fontSize: 20,
),
);
}),
- obx 도 변경이 되는 것만 빌드가 됨
// in getx_controller.dart
// observable 하는 값을 getter를 생성해서 obs 가 업데이트 될때 마다 getter 도 같이 업데이트가 됨
get sum => count1.value + count2.value;
// getter 임으로 sum 뒤에 value 붙이지 않음
Obx(() {
print("Sum BUILD");
return Text(
'Sum : ${controller.sum}',
style: TextStyle(
fontSize: 20,
),
);
},),
class 의 instance 를 obx 로 만들기
// in getx_controller.dart
// User model 생성
class User {
int id;
String name;
User({
required int id,
required String name,
}) : this.id = id,
this.name = name;
}
// model 로 부터 observable instance 생성
var user = User(id: 1, name: 'Jaocb').obs;
// observable instance 값 변경 하기
change({
required int id,
required String name,
}) {
// .update 을 해줘야 observable instance 를 변경 해줄 수 있음
user.update((val) {
val!.id = id;
val.name = name;
});
}
// in reactive.dart
Obx(() {
return Text(
'User : ${controller.user.value.id} / ${controller.user.value.name}',
style: TextStyle(
fontSize: 20,
),
);
}),
ElevatedButton(
onPressed: () {
controller.change(id: 2, name: 'Emma');
},
child: Text(
'Change User!',
style: TextStyle(
fontSize: 20,
),
),
),
- 단, list 나 map 같이 primitive 값이 아닌 경우에는 .value 를 사용하지 않고 사용합니다
// in getx_controller.dart
List testList = [1, 2, 3, 4, 5].obs;
// in reactive.dart
Obx(() {
return Text(
'List : ${controller.testList}',
style: TextStyle(
fontSize: 20,
),
);
}),
Observable Worker 기능
-
worker 를 사용하지 않는 상황이면 되도록 on update 를 사용해서 state management 하는 것이 좋은데, 만약 아래와 같은 상황일때는 observable worker 를 사용해야 합니다
-
obs 을 사용할때는 주로 4가지 worker 를 사용할 때 쓰입니다
-
주로 Debounce 를 유용하게 사용할 수 있는데 server 로 부터 fetch data 를 가지고 오는 상황에서 만약, user 가 form 에서 이 입력한 데이터를 서버로 보내서 검색한 후, Get 하는 상황에서 user 가 입력할때 마다 그 정보를 서버로 post, get 하는것보다
debounce
worker 를 사용하게 되면 user 가 입력이 끝나면 그때 server 로 post 학게 될때 자주 사용됩니다
// getx_controller.dart
@override
void onInit() {
super.onInit();
// 4가지 worker : Ever, Once, Debounce, Interval
// Ever : value 값이 변경 될때 마다 실행
ever(count1, (_) {
print('EVER: Count1 이 변경 될때마다 실행');
});
// Once : value 값이 한번 실행 할때 만 실행되는 worker
once(count1, (_) {
print('ONCE: 처음으로 count1 이 변경 되었을때');
});
// Debounce: value 값이 변경 되고 지정된 time Duration 값이 지나고 나서 실행되는 worker (만약 Duration 시간 내에 value 변경이 일어나면 debounce 는 실행되지 않다가 Duration 시간이 지났는데 변경이 일어나지 않으면 그때 한번만 worker 실행함)
debounce(
count1,
(_) {
print("DEBOUNCE: 1초간 디바운스 한 뒤에 실행");
},
time: Duration(seconds: 1),
);
// Interval: value 값이 변경되는 runtime 시간 동안 inteval로 Duration 일정 시간 간격으로 실행되는 worker (반복되는 작업동안에 주기적으로 실행됨)
interval(
count1,
(_) {
print("INTERVAL: 1초간 인터벌이 지나면 실행");
},
time: Duration(seconds: 1),
);
}
🔶 🔷 📌 🔑
Reference
GetX pub.dev - https://pub.dev/packages/get
The Flutter GetX Ecosystem ~ Dependency Injection - https://medium.com/flutter-community/the-flutter-getx-ecosystem-dependency-injection-8e763d0ec6b9
Terry’s Dev-Diary - https://terry1213.github.io/flutter/flutter-getx/
코드 팩토리 - https://youtu.be/wgJItCEL7hkhttps://youtu.be/wgJItCEL7hk
Leave a comment