KoreaMango 나무

Flutter State Management - 1. Provider, ChangeNotifier 에 대해 본문

Flutter

Flutter State Management - 1. Provider, ChangeNotifier 에 대해

KoreaMango 2024. 11. 9. 23:38

오늘은 Flutter의 상태관리에 대해 알아보려 합니다.

 

Flutter에서 데이터 상태관리를 하기 위해서는 여러가지 방법이 있습니다.

Provider, GetX, Bloc, ... 등등..

 

하지만 Flutter를 입문자라면 아마도 Provider를 통해서 데이터 상태관리를 할 것 입니다.

 

Flutter 공식 문서에서도 Flutter에서 Provider를 사용하는 것은 이해하기 쉽고, 코드를 많이 사용하지 않는다고 말합니다.

 

저도 provider가 Flutter에 기본적으로 내장되어 있는 줄 알았는데, 상태관리를 하기 위해서는 package를 설치해야 하더라구요.

 

https://pub.dev/packages/provider

 

provider | Flutter package

A wrapper around InheritedWidget to make them easier to use and more reusable.

pub.dev

 

여기 페이지를 참고하여 자신의 프로젝트에 추가해주시면 됩니다!

 

Provider를 사용하기 위해선 3가지 개념을 필수로 알아야 하는데요.

 

1. ChangeNotifier

2. ChangeNotifierProvider

3. Consumer

가 있습니다.

 

ChangeNotifier는 Flutter에 포함되어 있는 클래스로 Listener에게 변경 알림을 제공합니다.

 

사용 방법은 

class CartModel extends ChangeNotifier {
  /// Internal, private state of the cart.
  final List<Item> _items = [];

  /// An unmodifiable view of the items in the cart.
  UnmodifiableListView<Item> get items => UnmodifiableListView(_items);

  /// The current total price of all items (assuming all items cost $42).
  int get totalPrice => _items.length * 42;

  /// Adds [item] to cart. This and [removeAll] are the only ways to modify the
  /// cart from the outside.
  void add(Item item) {
    _items.add(item);
    // This call tells the widgets that are listening to this model to rebuild.
    notifyListeners();
  }

  /// Removes all items from the cart.
  void removeAll() {
    _items.clear();
    // This call tells the widgets that are listening to this model to rebuild.
    notifyListeners();
  }
}

 

이렇게 Class에 ChangeNotifier를 상속해주면 됩니다.

 

그리고 이 클래스의 상태값을 변경 시켜줬을 때, 리스너에게 전달을 하기 위해서는 notifyListeners();를 실행해줘야 합니다.

 

ChangeNotifierProvider는 위젯인데, 하위 항목에 ChangeNotifier의 인스턴스를 제공합니다.

ChangeNotifierProvider는 provider 패키지에 존재하므로 provider를 설치해야줘야해요 :)

 

ChangeNotifierProvider는 불필요하게 상위 계층에 놓을 필요가 없어요.

여러 개의 ChangeNotifierProvider를 하위 항목들에게 전달하고 싶으면 MutilProvider를 사용하면 됩니다 :)

 

/// ChangeNotifierProvider Example
void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => CartModel(),
      child: const MyApp(),
    ),
  );
}

/// MultiProvider Example
void main() {
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (context) => CartModel()),
        Provider(create: (context) => SomeOtherClass()),
      ],
      child: const MyApp(),
    ),
  );
}

 

마지막으로 Consumer에 대해 설명드리자면,

 

상위에서 상태값을 갖고 있는 ChangeNotifier, 넘겨주는 ChangerNotifierProvider가 있으면, 상태를 사용하는 곳도 있어야겠죠.

그 상태를 사용하려고 받는 위젯을 Consumer 위젯이라고 합니다.

 

이 Consumer 또한 ChangerNotifierProvider와 똑같이, 굳이 상위에서 쓸 필요가 없습니다.

가장 좋은 예시는 딱 사용하는 부분만 Consumer로 덮어주는거죠.

 

// DON'T DO THIS
return Consumer<CartModel>(
  builder: (context, cart, child) {
    return HumongousWidget(
      // ...
      child: AnotherMonstrousWidget(
        // ...
        child: Text('Total price: ${cart.totalPrice}'),
      ),
    );
  },
);

// DO THIS
return HumongousWidget(
  // ...
  child: AnotherMonstrousWidget(
    // ...
    child: Consumer<CartModel>(
      builder: (context, cart, child) {
        return Text('Total price: ${cart.totalPrice}');
      },
    ),
  ),
);

 

이렇게 말입니다.

 

추가적으로 Provider에 있는 함수를 가져오고 싶지만, 계속 Listen을 할 필요가 없으면, Listen을 끊어줄 수 있다고 하네요.

Provider.of<CartModel>(context, listen: false).removeAll();

리소스를 비교적 크게 먹는 Consumer라는 위젯을 사용하지 않고, 이렇게 사용해서 ChangerNotifier를 상속한 클래스에 접근한 다음, 

메소드를 실행할 수 있습니다.

 

위의 예시는 CartModel에 있는 removeAll이라는 함수를 실행시키는 예시 입니다.

 

provider 패키지에서 context에 extension으로 Provider.of를 조금 더 축약시켜놓은 

context.read 와 context.watch가 있으니 이것도 알아보시면 좋을 것 같네요 :)

 

출처: https://docs.flutter.dev/data-and-backend/state-mgmt/simple

 

Simple app state management

A simple form of state management.

docs.flutter.dev

 

Flutter 상태 관리의 가장 기본인 Provider에 대해 간단하게 알아봤는데요. 

 

정말 쉽긴 한 것 같아요.

 

그런데 조금 더 체계적인 아키텍처에서 사용하기에는 ChangeNotifierProvider와 Consumer가 중구난방으로 쓰일까봐 걱정이 되긴 하네요.

 

다음에는 GetX와 Bloc에 대해서도 알아보면 좋을 것 같아요.

 

그리고 dart 코드 블럭을 못 찾고 있는데, 글 작성할 때 dart 코드블럭 사용하는 방법에 대해 아시는 분 계신가요?..