본문 바로가기

운동하는 개발자/Flutter

13년차 응용프로그래머, Gemini에게 Flutter 배우기 - 3

728x90

UI 간에 값을 넘기고 넘기고 하는 방식이 상당히 고되었었고 
기존코드에도 전역변수를 남발하는 경우가 많았는데 
이 문제가 해결되는 Provider 사용법에 대해 학습함 (위젯간 직접참조 불가)

 

터미널 명령어로 설치

flutter pub add provider

 

코드 수정

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

// 1. ChangeNotifier 상속 (방송 능력을 갖춤)
class CartModel extends ChangeNotifier {
  int _totalPrice = 0; // 보호된 상태 데이터

  int get totalPrice => _totalPrice; // Getter

  // 상태를 변경하는 메서드
  void addPayment(int amount) {
    _totalPrice += amount;
    
    // 2. 핵심! "내 데이터가 바뀌었으니 나를 쳐다보는 놈들은 다 화면 다시 그려라!" 하고 방송을 쏩니다.
    notifyListeners(); 
  }
}

 

@override
Widget build(BuildContext context) {
  // 3. 수신기 장착: CartModel의 데이터를 쳐다보고 있다가, notifyListeners()가 호출되면 이 화면을 통째로 다시 그립니다.
  final cart = context.watch<CartModel>(); 

  return Scaffold(
    appBar: AppBar(title: const Text('메인 화면')),
    body: Center(
      child: Column(
        children: [
          // cart.totalPrice를 읽어옵니다. 값이 바뀌면 알아서 텍스트도 바뀝니다.
          Text('오늘의 총 매출: ${cart.totalPrice}원'), 
          
          ElevatedButton(
            // 버튼을 누르면 비즈니스 로직의 함수만 순수하게 호출합니다. UI 직접 제어는 없습니다.
            onPressed: () => cart.addPayment(15000), 
            child: const Text('15,000원 결제 추가'),
          ),
          SizedBox(height: 4),
          ElevatedButton(
            // 버튼을 누르면 UI 제어 없이 순수 비즈니스 로직 함수만 호출합니다.
            onPressed: () => cart.addPayment(-15000),
            style: ElevatedButton.styleFrom(
              padding: const EdgeInsets.all(16),
            ),
            child: const Text(
              '15,000원 결제 취소',
              style: TextStyle(fontSize: 18),
            ),
          ),          
        ],
      ),
    ),
  );
}

final cart = context.watch<CartModel>(); 수신기로 선언 뒤 
Cart에 addPayment()라는 단순 계산만 하는 비즈니스 로직 함수를 호출만 해도 변경된 값으로 UI가 갱신됨

UI가 스스로 상태를 가져야 하는지 아닌지에 따라서
StatefulWidget를 상속받을지 StatelessWidget를 상속받을지 정하면 됨
이는 1:N도 가능하여 다른 클래스에서도 watch가능

화면 갱신이 필요없는경우에는 watch가 아니라 read로 사용 가능

728x90