본문 바로가기

Flutter/07 State - Getx

[Flutter] GetX - Get.create 조합 예시

이번 카테고리는 GetX 의 Get.create 의 사용에 대해서 조금 자세히 알아보겠습니다.

개발환경 : 윈도우11, 안드로이드 스튜디오, flutter 3.0.1

Get 버전 - get: ^4.6.5

소스코드 위치 - Release 16_Get_create_example3 · mike-bskim/getx_test · GitHub

 

Release 16_Get_create_example3 · mike-bskim/getx_test

 

github.com

 

 

 

화면구성은 아래와 같다.

 

 

 

이전 블로그의 샘플 코드에서는 아래처럼 화면에서 접근했다.

 

// 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