728x90
์ง๊ธ๊น์ง StatefulWidget → MVVM ChangeNotifier → Provider ์์ผ๋ก ์ํ๊ด๋ฆฌ๋ฅผ ๊ณต๋ถํด๋ดค๋๋ฐ
์ด๋ฒ์๋ GetX ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํตํด ๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ์ ๊ฒฝํํด๋ณด๊ณ , ์ํ๊ด๋ฆฌ๊ฐ ์ผ๋ง๋ ๊ฐ๋จํด์ง ์ ์๋์ง ์์๋ณด๊ฒ ์ต๋๋ค!
์ด์ ๋ฐฉ์๋ค์ ๊ณตํต๋ ์์ฌ์
Provider๊น์ง์ ํจํด๋ค
// ChangeNotifier ๊ธฐ๋ฐ (MVVM, Provider ๊ณตํต)
class CounterViewModel extends ChangeNotifier {
int count = 0;
void countUp() {
count = count + 1;
notifyListeners(); // ๐ค ์ด๊ฑธ ๋งค๋ฒ ํธ์ถํด์ผ ํจ
}
void countDown() {
count = count - 1;
notifyListeners(); // ๐ค ๊น๋นกํ๋ฉด UI ์
๋ฐ์ดํธ ์๋จ
}
}
// UI์์ ์ฌ์ฉ
Consumer<CounterViewModel>(
builder: (context, viewModel, child) {
return Text('${viewModel.count}'); // ๐ค builder ํจ์ ํ์
}
)
๊ณตํต๋ ๋ถํธํจ๋ค:
- notifyListeners() ๊ฐ์ : ๋งค๋ฒ ์๋์ผ๋ก ํธ์ถํด์ผ ํจ
- Builder ํจํด: Consumer, ListenableBuilder ๋ฑ์ ๋ํผ ํ์
GetX : ๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ
GetX๋ ๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ(Reactive Programming) ๊ฐ๋ ์ Flutter์ ๋์ ํฉ๋๋ค.
ํต์ฌ ์์ด๋์ด
๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋๋ฉด → ์๋์ผ๋ก → UI๊ฐ ์
๋ฐ์ดํธ
"๋ฐ์ดํฐ์ ๋ณํ๋ฅผ ๊ฐ์งํด์ ์๋์ผ๋ก UI๋ฅผ ์ ๋ฐ์ดํธํด์ฃผ๋" ๊ฒฝํ์ ์ ๊ณตํฉ๋๋ค.
์ฝ๋ ๋ถ์: GetX
Controller: .obs์ ์ญํ
class GetXCounterController extends GetxController {
// ๋ฐ์ดํฐ (.obs = Observable)
var count = 0.obs; // ๊ด์ฐฐ ๊ฐ๋ฅํ ๋ณ์๋ก ์ ์ธ
// โก ๋ก์ง
void countUp() {
print('GetXCounterController - countUp count: $count');
count = count + 1; // notifyListeners() ํธ์ถ ๋ถํ์!
}
void countDown() {
print('GetXCounterController - countUp count: $count');
count = count - 1; // ์๋์ผ๋ก UI ์
๋ฐ์ดํธ๋จ!
}
}
ํต์ฌ ๋ณํ:
- .obs: ๋ณ์๋ฅผ ๊ด์ฐฐ ๊ฐ๋ฅํ๊ฒ ๋ง๋ฆ
- ์๋ ์๋ฆผ: ๊ฐ์ด ๋ณ๊ฒฝ๋๋ฉด ์๋์ผ๋ก ๊ตฌ๋ ์๋ค์๊ฒ ์๋ฆผ
- notifyListeners() ์ ๊ฑฐ: ๋ ์ด์ ์๋ ํธ์ถ ๋ถํ์
View: ์ปจํธ๋กค๋ฌ ๋ฑ๋ก๊ณผ ์ฌ์ฉ
class GetxCounterHomePage extends StatelessWidget {
GetxCounterHomePage({super.key});
// ์ปจํธ๋กค๋ฌ ๋ฑ๋ก
final GetXCounterController controller = Get.put(GetXCounterController());
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('GetX Counter App')),
body: SafeArea(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
spacing: 10,
children: [
// Obx: ๋ฐ์ํ ์์ ฏ
Obx(() => Text(
'Counter.count : ${controller.count}',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30),
)),
ElevatedButton(
onPressed: () {
controller.countUp(); // ๋จ์ํ ๋ฉ์๋ ํธ์ถ
},
child: Text('์นด์ดํธ ์ฆ๊ฐ'),
),
ElevatedButton(
onPressed: () {
controller.countDown();
},
child: Text('์นด์ดํธ ๊ฐ์'),
),
],
)
),
),
);
}
}
ํต์ฌ ๋ณํ:
- Get.put(): ์ปจํธ๋กค๋ฌ๋ฅผ GetX ์์คํ ์ ๋ฑ๋ก
- Obx(): ๋ฐ์ํ ์์ ฏ, ๋ด๋ถ ๋ณ์ ๋ณ๊ฒฝ ์ ์๋ ๋ฆฌ๋น๋
- ์ง์ ์ ๊ทผ: controller.count๋ก ๊ฐ๋จํ๊ฒ ์ ๊ทผ
main.dart: GetMaterialApp
void main() {
runApp(GetMaterialApp(home: GetXCounterApp()));
}
๋ณํ:
- MaterialApp → GetMaterialApp: GetX ๊ธฐ๋ฅ ํ์ฑํ
- Provider ์ค์ ๋ถํ์: ๋ณ๋ Provider ๋ํ ์์
์ด์ ๋ฐฉ์๋ค๊ณผ์ ๋น๊ต
์ํ ๋ณ์ ์ ์ธ
// ChangeNotifier/Provider: ์ผ๋ฐ ๋ณ์ + ์๋ ์๋ฆผ
class CounterViewModel extends ChangeNotifier {
int count = 0; // ์ผ๋ฐ ๋ณ์
void countUp() {
count++;
notifyListeners(); // ์๋ ํธ์ถ ํ์
}
}
// GetX: ๊ด์ฐฐ ๊ฐ๋ฅํ ๋ณ์ + ์๋ ์๋ฆผ
class GetXCounterController extends GetxController {
var count = 0.obs; // ๊ด์ฐฐ ๊ฐ๋ฅํ ๋ณ์
void countUp() {
count++; // ์๋์ผ๋ก ์๋ฆผ
}
}
UI ์ ๋ฐ์ดํธ
// Provider: Builder ํจํด ํ์
Consumer<CounterViewModel>(
builder: (context, viewModel, child) {
return Text('${viewModel.count}');
}
)
// GetX: ๊ฐ๋จํ Obx ๋ํ
Obx(() => Text('${controller.count}'))
์ธ์คํด์ค ๊ด๋ฆฌ
// Provider: main.dart์์ ์ค์
void main() {
runApp(
ChangeNotifierProvider<CounterViewModel>(
create: (context) => CounterViewModel(),
child: MyApp(),
)
);
}
// GetX: ์ฌ์ฉํ๋ ๊ณณ์์ ๋ฐ๋ก ๋ฑ๋ก
class HomePage extends StatelessWidget {
final controller = Get.put(GetXCounterController());
}
๊ฐ๋ฐ ์๋
// ๊ธฐ์กด ๋ฐฉ์: 5-6๋จ๊ณ
// 1. ViewModel ์์ฑ
// 2. ChangeNotifier ์์
// 3. notifyListeners() ํธ์ถ
// 4. Provider ์ค์
// 5. Consumer ๋ํ
// 6. UI ๊ตฌ์ฑ
// GetX: 3๋จ๊ณ
// 1. Controller ์์ฑ (.obs ๋ณ์)
// 2. Get.put()์ผ๋ก ๋ฑ๋ก
// 3. Obx()๋ก UI ๋ํ
๋ง๋ฌด๋ฆฌ
GetX๋ ๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ์ Flutter์์ ์ฝ๊ฒ ๊ฒฝํํ ์ ์๊ฒ ํด์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค.
GetX์ ํน์ง:
- .obs: ๊ด์ฐฐ ๊ฐ๋ฅํ ๋ณ์๋ก ์๋ ์๋ฆผ
- Obx(): ๋ฐ์ํ UI ์ ๋ฐ์ดํธ
- Get.put(): ๊ฐ๋จํ ์์กด์ฑ ๋ฑ๋ก
GetX๋ "์ํ๊ด๋ฆฌ๊ฐ ์ด๋ ๊ฒ ๊ฐ๋จํ ์ ์๊ตฌ๋!"ํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค.
'๐ฅ Bread Basics > Flutter' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Flutter] Riverpod ์ํ๊ด๋ฆฌ:: ๊ตฌ์กฐํ๋ ์ ๊ทผ๋ฒ๊ณผ ํ์ ์์ ์ฑ (0) | 2025.06.27 |
---|---|
[Flutter] Provider ์ํ๊ด๋ฆฌ:: ChangeNotifier๋ฅผ ๋ ์ฒด๊ณ์ ์ผ๋ก (0) | 2025.06.27 |
[Flutter] MVVM ChangeNotifier:: (ํ๋ฉด) / (๋ฐ์ดํฐ, ๋ก์ง) ๋ฐ๋ก (1) | 2025.06.27 |
[Flutter] StatefulWidget:: ํ๋ฉด, ๋ฐ์ดํฐ, ๋ก์ง์ ํ ๋ฒ์ (0) | 2025.06.27 |
Dart ์ธ์ด ๊ธฐ๋ณธ๊ธฐ ๋ฐฐ์ฐ๊ธฐ (0) | 2025.04.28 |
mixin, sealed, base ํด๋์ค (0) | 2025.04.25 |
Record(ํํ), Destructuring (0) | 2025.04.25 |
Future, async, await, stream, listen, sink, yield (0) | 2025.04.25 |