티스토리 뷰

반응형

아래 움짤처럼 여러 화면에서 상태를 공유해야할때 어떻게 해야하는지 State management 문서를 살펴보겠습니다. 

 

https://flutter.dev/docs/development/data-and-backend/state-mgmt/intro

 

 

1) 선언적으로 생각하기 

 

우선 선언적으로 생각하라고 합니다. SwiftUI 처럼 state가 바뀌면 뷰를 아예 다시 그리는 컨셉 🆗👌

 

 

2) 임시상태 vs 앱상태 (Ephemeral state vs app state)

그 다음에 임시 상태와 앱상태를 구분하라고 합니다. (Ephemeral state vs app state)

 

임시상태는 말그대로 단일 위젯에만 딱 포함되는 상태입니다. (다른 위젯들이 이 위젯의 상태에 대해 몰라도됨)

그리고 사용자가 앱을 닫았다가 다시 시작하면 초기값으로 재설정되도 되는 상태입니다. 

 

이런 경우 setState()를 써서 상태관리를 해주면 됩니다. 

 

 

앱상태는 앱의 여러 화면에 대해서 공유하고 싶고 일시적이지 않은 상태를 말합니다. 

예를 들어 이런 것들을 앱상태라고 합니다. 

앱 상태 관리를 어떻게 하는지는 아래에서 살펴볼게요-!! 

 

 

아래 그림으로 앱상태와 임시상태를 나눠볼 수 도 있겠습니다. 

 

 

3) 앱상태관리하기 with Provider - Provider가 필요한 이유

 

옵션문서를 보면 provider, Redux, BLoC / Rx, MobX 등 다양한 선택지들이 있는데요

문서에서는 provider를 소개하고 있습니다. 

그 전에 Provider가 왜 필요한지 살펴볼게요!! 

 

 

이런 앱이 있다고 해보겠습니다. 

 

 

위젯 트리는 이렇게 되어있습니다. 

 

MyListItem은 카트에 자신을 추가 할 수 있어야합니다. 그리고 현재 표시된 항목이 이미 카트에 있는지 여부를도 확인할 수 있어야합니다. 

 

그러면 Cart 상태를 어디에 두어야할까요?!?!

 

Flutter에서는 특정 상태를 사용하는 위젯들에 특정 상태를 두는게 합리적이라고 합니다.

 

왜냐면 '선언적으로 생각하기'에서 본 것 처럼 UI를 변경하려면 다시 빌드해야하기 때문입니다. 

 

즉 MyListItem와 MyCart의 위인 MyApp에 Cart 상태를 두면 

Cart상태가 변할때 MyApp이 다시 빌드되고 하위 위젯들도 같이 빌드되면서 MyListItem와 MyCart가 업데이트 되게 되는 것입니다. 

 

 

 

 

이제 Cart 상태를 어디 둘지 알았으니까 Cart 상태에 어떻게 접근할 수 있는지 살펴볼게요-!! 

 

MyListItem은 Cart에 어떻게 접근할 수 있을까요?!

가장 간단한 방법은 MyListItem이 콜백을 넘겨주서 이 아이템이 클릭될때 콜백을 실행하도록 하는 것입니다. 

 

 

하지만!! 

위젯트리가 늘어난다면 위젯에서 위젯으로, 또 위젯에서 위젯으로,, 많은 콜백을 전달해야되는 방법입니다,,

(근데 InheritedWidget, InheritedNotifier, InheritedModel 을 사용하면 상태를 자손에게 전달할 수 있는 더 편한 방법이 있다고는 합니다.)

 

 

그래서 우리는 Provider를 써보도록 하겠습니다0!! 이것을 쓰면 콜백이나 InheritedWidget에 대하여 걱정할 필요가 없다고 합니다. 

(Provider는 따로 설치해야하는 패키지 입니다. )

 

 

4) 앱상태관리하기 with Provider - Provider의 컨셉

 

Provider에는 

세가지 컨셉이 있습니다,

 

- ChangeNotifier

- ChangeNotifierProvider

- Consumer 

 

 

ChangeNotifier

 

ChangeNotifier는 리스너에게 변경 알림을 제공하는 Flutter SDK에 포함 된 간단한 클래스입니다. (flutter:foundation 안에 있는 클래스입니다.)

즉 무언가가 ChangeNotifier 타입이면 우리는 그것의 변화들을 구독할 수 있습니다.

Observable같은 것이라고 하네요 

 

 

Provider에서는 ChangeNotifier가 앱 상태를 캡슐화하는 한 방법이라고 합니다. 

 

 

예를 들어 이렇게 CartModel이 ChangeNotifier를 extends하게 하고 

카트에 아이템이 추가될때다 카트가 다 비워질때 

notifyListeners() 를 call하도록 해줄 수 있습니다.

 

이 메소드를 부르면 app의 UI도 업데이트 된다고 합니다. 

 

 

이런식으로 unit test code도 작성할 수 있다고 합니다. 

 

 

ChangeNotifierProvider

 

ChangeNotifierProvider는 자손들에게 ChangeNotifier 인스턴스를 제공해주는 친구라고 합니다.

이 클래스는 provider 패키지안에 있습니다.

 

우리는 ChangeNotifierProvider를 어디에 둘지 위에서 이미 결정했습니다. 바로 MyApp에-!!

MyApp을 아래와 같이 ChangeNotifierProvider로 감싸주세요

 

 

 

만약 여러 클래스를 제공하고 싶다면 MultiProvider라는 것도 있다고 합니다. 

 

 

Consumer

 

Consumer를 통해서 앱상태에 접근해줄 수 있습니다. 

아래 코드처럼 Consumer에 액세스하려는 모델의 타입(우리는 CartModel)을 지정해주면 됩니다. 

그리고 builder는 ChangeNotifier가 변경될때마다 호출되는 함수입니다.

 

즉  CartModel에서 notifyListeners() 가 호출되면 모든 Consumer<CartModel>의 builder 메소드가 호출됩니다. 

 

그리고 위의 예제처럼 그냥 Text를 리턴해주는 것 말고

Consumer위젯에 deep widget tree를 그리고 싶다면 

 

이렇게 하지말고 

 

 

이렇게 하라고 합니다. 

 

 

 

5) 앱상태관리하기 with Provider - Provider.of

 

때로는 UI를 변경하기 위해 모델의 데이터가 필요하지는 않지만 모델의 데이터에 액세스 하고 싶을때가 있습니다. 

예를 들어 ClearCart 버튼은 카트의 내용물을 표시 할 필요가 없으며 clear( )메서드 를 호출하기만하면 됩니다 .

 

이때 Consumer<CartModel>를 쓰는 것은 낭비입니다. 

다시 빌드할 필요가 없는 위젯을 다시 빌드하도록 프레임워크에 요청하는 것이니까요-!! 

 

 

그럴땐 Provider.of 를 쓰면 됩니다. (listen을 false로 해서)

 

 

그러면 notifyListeners가 불려도 이 위젯은 다시 그려지지 않게 됩니다. 

 

 

Reference

 

flutter.dev/docs/development/data-and-backend/state-mgmt/simple

 

Simple app state management

A simple form of state management.

flutter.dev

 

반응형
댓글