이번 카테고리는 GetX 의 Get.create 의 사용에 대해서 조금 자세히 알아보겠습니다.
개발환경 : 윈도우11, 안드로이드 스튜디오, flutter 3.0.1
Get 버전 - get: ^4.6.5
소스코드 위치 - Release 16_Get_create_example3 · mike-bskim/getx_test · GitHub
화면구성은 아래와 같다.
이전 블로그의 샘플 코드에서는 아래처럼 화면에서 접근했다.
// injected by Get.create
final ShoppingController controller = Get.find();
// injected by Get.put
final ShoppingController controllerTotal = Get.find(tag: 'total');
이번에는 다양한 조합으로 테스트 했다.
Get.create + GetWidget + Obx - 정상동작
Get.create + Stateless + GetBuilder - 정상동작
Get.create + Stateless + Obx - 정상 동작하지 않음.
오늘의 프로젝트 주요파일은 아래와 같다.
./src/pages/dependencys/dependency_manage_page.dart
./src/binding/cart_binding.dart
./src/controller/cart_get_widget_controller.dart
./src/controller/cart_get_widget_item_controller.dart
./src/controller/cart_get_builder_controller.dart
./src/controller/cart_get_builder_item_controller.dart
./src/controller/cart_get_stateless_controller.dart
./src/controller/cart_get_stateless_item_controller.dart
./src/pages/create_sample/cart/cart_get_widget_page.dart
./src/pages/create_sample/cart/cart_get_builder_page.dart
./src/pages/create_sample/cart/cart_stateless_page.dart
./src/pages/create_sample/cart/cart_page.dart
./src/pages/dependencys/dependency_manage_page.dart - 추가사항만 표시함.
ElevatedButton(
style: elevatedButtonStyle,
child: Text("Get.create 비교 예시", style: textStyle),
onPressed: () {
Get.to(() => const CartPage());
},
),
./src/binding/cart_binding.dart
import 'package:get/get.dart';
import '../controller/cart_get_builder_controller.dart';
import '../controller/cart_get_builder_item_controller.dart';
import '../controller/cart_get_stateless_controller.dart';
import '../controller/cart_get_stateless_item_controller.dart';
import '../controller/cart_get_widget_controller.dart';
import '../controller/cart_get_widget_item_controller.dart';
class GetBuilderBinding implements Bindings {
@override
void dependencies() {
// total by get.put
Get.put(CartGetBuilderController());
// each count by get.create
Get.create(() => CartGetBuilderItemController());
}
}
class GetStatelessBinding implements Bindings {
@override
void dependencies() {
// total by get.put
Get.put(CartGetStatelessController());
// each count by get.create
Get.create(() => CartGetStatelessItemController());
}
}
class GetWidgetBinding implements Bindings {
@override
void dependencies() {
// total by get.put
Get.put(CartGetWidgetController());
// each count by get.create
Get.create(() => CartGetWidgetItemController());
}
}
./src/controller/cart_get_widget_controller.dart
import 'package:get/get.dart';
class CartGetWidgetController extends GetxController {
final totalNumberOfProducts = 0.obs;
final products = ['prod 1', 'prod 2', 'prod 3'].obs;
static CartGetWidgetController get to => Get.find();
void addProduct() => products.add('prod ${products.length + 1}');
}
./src/controller/cart_get_widget_item_controller.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'cart_get_widget_controller.dart';
class CartGetWidgetItemController extends GetxController {
final quantity = 0.obs;
static CartGetWidgetItemController get to => Get.find();
void increment() {
quantity.value++;
CartGetWidgetController.to.totalNumberOfProducts.value++;
}
void decrement() {
if (quantity.value > 0) {
quantity.value--;
CartGetWidgetController.to.totalNumberOfProducts.value--;
}
}
@override
void onClose() {
debugPrint('(onClose)hashCode: $hashCode');
super.onClose();
}
}
./src/controller/cart_get_builder_controller.dart
import 'package:get/get.dart';
class CartGetBuilderController extends GetxController {
final totalNumberOfProducts = 0.obs;
final products = ['prod 1', 'prod 2', 'prod 3'].obs;
static CartGetBuilderController get to => Get.find();
void addProduct() => products.add('prod ${products.length + 1}');
}
./src/controller/cart_get_builder_item_controller.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'cart_get_builder_controller.dart';
class CartGetBuilderItemController extends GetxController {
int quantity = 0;
static CartGetBuilderItemController get to => Get.find();
void increment() {
quantity++;
CartGetBuilderController.to.totalNumberOfProducts.value++;
update();
}
void decrement() {
if (quantity > 0) {
quantity--;
CartGetBuilderController.to.totalNumberOfProducts.value--;
update();
}
}
@override
void onClose() {
debugPrint('(onClose)hashCode: $hashCode');
super.onClose();
}
}
./src/controller/cart_get_stateless_controller.dart
import 'package:get/get.dart';
class CartGetStatelessController extends GetxController {
final totalNumberOfProducts = 0.obs;
final products = ['prod 1', 'prod 2', 'prod 3'].obs;
static CartGetStatelessController get to => Get.find();
void addProduct() => products.add('prod ${products.length + 1}');
}
./src/controller/cart_get_stateless_item_controller.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'cart_get_stateless_controller.dart';
class CartGetStatelessItemController extends GetxController {
final quantity = 0.obs;
static CartGetStatelessItemController get to => Get.find();
void increment() {
quantity.value++;
CartGetStatelessController.to.totalNumberOfProducts.value++;
}
void decrement() {
if (quantity.value > 0) {
quantity.value--;
CartGetStatelessController.to.totalNumberOfProducts.value--;
}
}
@override
void onClose() {
debugPrint('(onClose)hashCode: $hashCode');
super.onClose();
}
}
./src/pages/create_sample/cart/cart_get_widget_page.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../controller/cart_get_widget_controller.dart';
import '../../../controller/cart_get_widget_item_controller.dart';
class CartGetViewPage extends GetView<CartGetWidgetController> {
const CartGetViewPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('GetWidget Cart'),
),
body: Column(
children: [
const SizedBox(height: 20.0),
Obx(
() => Text(
'Total: ${controller.totalNumberOfProducts} items in cart',
style: const TextStyle(
fontSize: 24.0,
fontWeight: FontWeight.bold,
),
),
),
const SizedBox(height: 20.0),
Expanded(
child: Obx(() {
return ListView.separated(
itemCount: controller.products.length,
itemBuilder: (BuildContext context, int index) {
String product = controller.products[index];
return CartItem(product: product);
},
separatorBuilder: (context, index) => const Divider(
color: Colors.grey,
height: 1,
),
);
}),
),
],
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () {
controller.addProduct();
},
),
);
}
}
class CartItem extends GetWidget<CartGetWidgetItemController> {
final String product;
const CartItem({Key? key, required this.product}) : super(key: key);
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
product,
style: const TextStyle(fontSize: 18.0),
),
Obx(
() => Text(
'Qty: ${controller.quantity.value}',
style: const TextStyle(fontSize: 18.0),
),
),
Row(
children: [
IconButton(
onPressed: () {
debugPrint(
'hashCode: ${controller.hashCode}, ${controller.quantity}');
controller.increment();
},
icon: const Icon(Icons.add),
),
IconButton(
onPressed: () => controller.decrement(),
icon: const Icon(Icons.remove),
),
],
),
],
);
}
}
./src/pages/create_sample/cart/cart_get_builder_page.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../controller/cart_get_builder_controller.dart';
import '../../../controller/cart_get_builder_item_controller.dart';
class CartGetBuilderPage extends GetView<CartGetBuilderController> {
const CartGetBuilderPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('GetBuilder Cart'),
),
body: Column(
children: [
const SizedBox(height: 20.0),
Obx(
() => Text(
'Total: ${controller.totalNumberOfProducts} items in cart',
style: const TextStyle(
fontSize: 24.0,
fontWeight: FontWeight.bold,
),
),
),
const SizedBox(height: 20.0),
Expanded(
child: Obx(() {
return ListView.separated(
itemCount: controller.products.length,
itemBuilder: (BuildContext context, int index) {
String product = controller.products[index];
return CartItem(product: product);
},
separatorBuilder: (context, index) => const Divider(
color: Colors.grey,
height: 1,
),
);
}),
),
],
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () {
controller.addProduct();
},
),
);
}
}
class CartItem extends StatelessWidget {
final String product;
const CartItem({Key? key, required this.product}) : super(key: key);
@override
Widget build(BuildContext context) {
return GetBuilder<CartGetBuilderItemController>(
builder: (controller) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
product,
style: const TextStyle(fontSize: 18.0),
),
Text(
'Qty: ${controller.quantity}',
style: const TextStyle(fontSize: 18.0),
),
Row(
children: [
IconButton(
onPressed: () {
debugPrint(
'hashCode: ${controller.hashCode}, ${controller.quantity}');
controller.increment();
},
icon: const Icon(Icons.add),
),
IconButton(
onPressed: () => controller.decrement(),
icon: const Icon(Icons.remove),
),
],
),
],
);
},
);
}
}
./src/pages/create_sample/cart/cart_stateless_page.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../controller/cart_get_stateless_controller.dart';
import '../../../controller/cart_get_stateless_item_controller.dart';
class CartStatelessPage extends GetView<CartGetStatelessController> {
const CartStatelessPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Stateless Cart'),
),
body: Column(
children: [
const SizedBox(height: 20.0),
Obx(
() => Text(
'Total: ${controller.totalNumberOfProducts} items in cart',
style: const TextStyle(
fontSize: 24.0,
fontWeight: FontWeight.bold,
),
),
),
const SizedBox(height: 20.0),
Expanded(
child: Obx(() {
return ListView.separated(
itemCount: controller.products.length,
itemBuilder: (BuildContext context, int index) {
String product = controller.products[index];
return CartItem(product: product);
},
separatorBuilder: (context, index) => const Divider(
color: Colors.grey,
height: 1,
),
);
}),
),
],
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () {
CartGetStatelessController.to.addProduct();
},
),
);
}
}
class CartItem extends StatelessWidget {
final String product;
const CartItem({Key? key, required this.product}) : super(key: key);
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
product,
style: const TextStyle(fontSize: 18.0),
),
Obx(
() => Text(
'Qty: ${CartGetStatelessItemController.to.quantity.value}',
style: const TextStyle(fontSize: 18.0),
),
),
Row(
children: [
IconButton(
onPressed: () {
debugPrint(
'hashCode: ${CartGetStatelessItemController.to.hashCode}, ${CartGetStatelessItemController.to.quantity}');
CartGetStatelessItemController.to.increment();
},
icon: const Icon(Icons.add),
),
IconButton(
onPressed: () => CartGetStatelessItemController.to.decrement(),
icon: const Icon(Icons.remove),
),
],
),
],
);
}
}
./src/pages/create_sample/cart/cart_page.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../binding/cart_binding.dart';
import 'cart_get_builder_page.dart';
import 'cart_get_widget_page.dart';
import 'cart_stateless_page.dart';
class CartPage extends StatelessWidget {
const CartPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
ButtonStyle elevatedButtonStyle = ElevatedButton.styleFrom(
minimumSize: const Size(280.0, 40.0),
padding: const EdgeInsets.symmetric(vertical: 12));
SizedBox sizedBox = const SizedBox(height: 16,);
return Scaffold(
appBar: AppBar(
title: const Text('Get.create 비교 예시'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
style: elevatedButtonStyle,
child: const Text(
'Go to GetWidget Cart',
style: TextStyle(fontSize: 20.0),
),
onPressed: () {
Get.to(() => const CartGetViewPage(),
binding: GetWidgetBinding());
},
),
sizedBox,
ElevatedButton(
style: elevatedButtonStyle,
child: const Text(
'Go to GetBuilder Cart',
style: TextStyle(fontSize: 20.0),
),
onPressed: () {
Get.to(() => const CartGetBuilderPage(),
binding: GetBuilderBinding());
},
),
sizedBox,
ElevatedButton(
style: elevatedButtonStyle,
child: const Text(
'Go to Stateless Cart',
style: TextStyle(fontSize: 20.0),
),
onPressed: () {
Get.to(() => const CartStatelessPage(),
binding: GetStatelessBinding());
},
),
],
),
),
);
}
}
화면 결과는 아래와 같다. Stateless 화면이 정상동작하지 않음을 알수 있다.
3번째 경우는 아래와 같이 수정하면 정상동작한다.
./src/controller/cart_get_stateless_item_controller.dart - static 부분 주석 처리.
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'cart_get_stateless_controller.dart';
class CartGetStatelessItemController extends GetxController {
final quantity = 0.obs;
// 아래 주석 처리
// static CartGetStatelessItemController get to => Get.find();
void increment() {
quantity.value++;
CartGetStatelessController.to.totalNumberOfProducts.value++;
}
void decrement() {
if (quantity.value > 0) {
quantity.value--;
CartGetStatelessController.to.totalNumberOfProducts.value--;
}
}
@override
void onClose() {
debugPrint('(onClose)hashCode: $hashCode');
super.onClose();
}
}
./src/pages/create_sample/cart/cart_stateless_page.dart - 일부분 아래처럼 수정.
class CartItem extends StatefulWidget {
final String product;
const CartItem({Key? key, required this.product}) : super(key: key);
@override
State<CartItem> createState() => _CartItemState();
}
class _CartItemState extends State<CartItem> {
late CartGetStatelessItemController cartGetStatelessItemController;
@override
void initState() {
cartGetStatelessItemController = Get.find();
super.initState();
}
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
widget.product,
style: const TextStyle(fontSize: 18.0),
),
Obx(
() => Text(
// 'Qty: ${CartGetStatelessItemController.to.quantity.value}',
'Qty: ${cartGetStatelessItemController.quantity.value}',
style: const TextStyle(fontSize: 18.0),
),
),
Row(
children: [
IconButton(
onPressed: () {
debugPrint(
// 'hashCode: ${CartGetStatelessItemController.to.hashCode}, ${CartGetStatelessItemController.to.quantity}');
'hashCode: ${cartGetStatelessItemController.hashCode}, ${cartGetStatelessItemController.quantity}');
// CartGetStatelessItemController.to.increment();
cartGetStatelessItemController.increment();
},
icon: const Icon(Icons.add),
),
IconButton(
// onPressed: () => CartGetStatelessItemController.to.decrement(),
onPressed: () => cartGetStatelessItemController.decrement(),
icon: const Icon(Icons.remove),
),
],
),
],
);
}
}
[참고자료] 헤비프랜
- https://www.youtube.com/watch?v=spNThdCajS0&list=PLGJ958IePUyDQwYbPcz-5W9o4p1__20V0&index=11
'Flutter > 07 State - Getx' 카테고리의 다른 글
[Flutter] GetX - Get.create 예시 (0) | 2022.06.09 |
---|---|
[Flutter] Getx - GetxService (0) | 2022.06.08 |
[Flutter] Getx - Binding (0) | 2022.06.07 |
[Flutter] GetX - Dependency injection (0) | 2022.06.07 |
[Flutter] GetX - State management(reactive) (0) | 2022.06.07 |