공부 일기/TIL

Flutter 창업반 6주차 TIL2 상태 관리 패키지(RiverPod)관련 복습/실습

oosuhada 2024. 12. 3. 11:08

Riverpod는 Flutter/Dart 환경에서 상태 관리를 쉽게 할 수 있도록 도와주는 라이브러리입니다. 

Riverpod을 사용하면 ViewModel의 역할을 쉽게 구현할 수 있으며, 

View(위젯)에서 상태를 관찰하고 업데이트하는 과정을 간단하게 처리할 수 있습니다. 

 

아래는 Riverpod을 사용하는 방법에 대한 단계별 설명입니다.


Riverpod의 주요 개념
Riverpod은 Provider의 아나그램으로, 반응형 캐싱 프레임워크입니다.
비동기 요청과 오류 처리를 자동으로 관리하며, 필요한 경우 데이터를 자동으로 다시 가져옵니다

 

사용법
1. 상태 클래스 정의하기
먼저 관리할 데이터를 담을 상태 클래스를 정의합니다.

class HomeState {
  int counter;
  HomeState(this.counter);
}

 

2. ViewModel 클래스 만들기
Notifier를 상속받는 ViewModel 클래스를 만듭니다. 

Notifier를 상속받으면 상태를 저장하고 업데이트할 수 있는 기능을 제공합니다.

class HomeViewModel extends Notifier<HomeState> {
  @override
  HomeState build() {
    return HomeState(1); // 초기 상태값 설정
  }

  void updateState() {
    state = HomeState(state.counter + 1); // 새로운 객체로 상태 업데이트
  }
}

 

3. NotifierProvider 생성하기
ViewModel을 관리하고 공급해 줄 NotifierProvider 객체를 생성합니다. 

이 공급자는 View에서 ViewModel을 요청할 때 사용됩니다.

final homeViewModelProvider = NotifierProvider<HomeViewModel, HomeState>(
  () => HomeViewModel(),
);

 

4. Widget에서 ViewModel 사용하기
Consumer 위젯을 사용하여 ViewModel에 접근합니다. 

WidgetRef를 통해 상태나 뷰모델에 접근할 수 있습니다.

Consumer(
  builder: (context, ref, child) {
    final state = ref.watch(homeViewModelProvider); // 상태 변경 감지 및 사용
    return Column(
      children: [
        Text('Counter: ${state.counter}'),
        ElevatedButton(
          onPressed: () => ref.read(homeViewModelProvider.notifier).updateState(),
          child: Text('Increment'),
        ),
      ],
    );
  },
)

 

 

5. ProviderScope로 앱 감싸기
앱의 최상위 위젯을 ProviderScope로 감싸서 Riverpod이 전체 앱에서 작동하도록 합니다.

void main() {
  runApp(const ProviderScope(child: MyApp()));
}

 

요약


상태 클래스: 관리할 데이터를 정의합니다.
ViewModel: Notifier를 상속받아 상태를 관리합니다.
NotifierProvider: ViewModel을 공급하고 관리합니다.
Consumer: 위젯에서 상태와 뷰모델에 접근하여 UI를 업데이트합니다.
ProviderScope: 앱의 최상위에서 Riverpod이 작동하도록 설정합니다.
이러한 구조를 통해 Riverpod은 Flutter 애플리케이션에서 효율적인 상태 관리를 지원하며, 복잡한 비즈니스 로직을 간단히 구현할 수 있게 해줍니다

 

 

// Notifier를 상속받으면 상태를 저장하고 업데이트할 수 있는 기능을 갖는다(ViewModel의 구실 가능)
// (Notifier 상속 시 이 ViewModel 이 어떤 상태를 관리하는지 제너릭으로 지정)
class HomeViewModel extends Notifier<HomeState> {

	// Notifier 클래스의 build 메서드를 재정의 해서
	// 초기 상태값 return 해주기
	// => HomeViewModel 이 생성되면 build 메서드의 리턴값으로 상태가 초기화
  @override
  HomeState build() {
    return HomeState(1);
  }
  
  void updateState(){
	  // 상태를 업데이트 해줄 땐 새로운 객체를 만들어 변경
	  state = HomeState(state.counter + 1);
	  // 새로운 객체를 state에 할당하지 않으면 자신을 바라보는 View에게
	  // 상태가 변경되었다고 알리지 않음
		//	state.coutner++; // => X
  }
}

 

이 코드는 Dart 언어로 작성된 HomeViewModel 클래스를 정의하고 있습니다. 이 클래스는 상태 관리를 위한 ViewModel의 역할을 수행합니다. 주요 특징들을 살펴보겠습니다:


상속 (Inheritance)

class HomeViewModel extends Notifier<HomeState>

 

여기서 HomeViewModel은 Notifier 클래스를 상속받고 있습니다. 상속은 한 클래스가 다른 클래스의 특성(속성과 메서드)을 물려받는 객체 지향 프로그래밍의 핵심 개념입니다. 이를 통해 HomeViewModel은 Notifier 클래스의 모든 기능을 사용할 수 있게 됩니다.

 

제네릭 (Generic)

Notifier<HomeState>

 

여기서 <HomeState>가 제네릭 부분입니다. 제네릭은 클래스나 메서드가 다양한 데이터 타입으로 작동할 수 있게 해주는 프로그래밍 기법입니다. 이 경우, Notifier 클래스가 HomeState 타입의 상태를 관리하도록 지정하고 있습니다.

 

주요 메서드 - build 메서드

@override
HomeState build() {
  return HomeState(1);
}


이 메서드는 Notifier 클래스의 build 메서드를 오버라이드(재정의)하고 있습니다. HomeViewModel이 생성될 때 초기 상태값을 반환합니다.


주요 메서드 - updateState 메서드

void updateState(){
  state = HomeState(state.counter + 1);
}


이 메서드는 상태를 업데이트합니다. 새로운 HomeState 객체를 생성하여 state에 할당함으로써 상태 변경을 알립니다.

 

상태 관리
Notifier 클래스를 상속받음으로써, HomeViewModel은 상태를 저장하고 업데이트할 수 있는 기능을 갖게 됩니다. state 속성을 통해 현재 상태에 접근하고 변경할 수 있습니다.


이러한 구조를 통해 HomeViewModel은 UI와 비즈니스 로직을 분리하고, 상태 변경을 효율적으로 관리할 수 있게 됩니다. 상태가 변경될 때마다 이를 바라보고 있는 View들에게 자동으로 알림이 가게 되어, UI를 업데이트할 수 있습니다.

 

 

📚 어떤 장점이 있을까요?

- 하위 위젯에 불필요하게 파라미터 넘겨줄 필요 없어짐(하위 위젯에서 Consumer 쓰면됨)
- 전역 상태 관리 가능(ViewModel 공급을 riverpod이 해주니깐)
- 위젯을 그리는 코드는 Widget에서, 상태 관리는 별도의 클래스에서 하니 유지보수 용이

**통신 시 사용법 정리**

- RiverPod 패키지 추가 `flutter pub add flutter_riverpod`
- main 함수에서 최상위 위젯을 `ProviderScope` 로 감싸기
- `Widget` 구현
- 데이터를 담을 `Model` 클래스 만들기
- 모델 가져오는 `Repository` 클래스 만들기
- `Widget` 에서 관리될 상태 클래스 만들기
- 상태를 관리할 `ViewModel` 만들기(`Notifier` 상속)
    - 최초 상태 `build` 메서드 재정의 해서 설정
    - `Repotory`에서 데이터 가져와서 상태 업데이트 하는 함수 작성
- ViewModel을 공급할 `viewModelProvider`(`NotifierProvider` 객체) 만들기
- `Widget` 에서 `Consumer` 위젯 사용해서 데이터 씌우기 및 함수 연결
    - 상태 업데이트 될 때 위젯이 변경되길 원하면 `ref.watch`
    - 한번만 값을 받아오고 싶으면 `ref.read`
    - ViewModel의 메서드를 사용하고 싶으면 `ref.read` 에 `viewModelProvider.notifier` 넘겨주기

 

https://github.com/oosuhada/flutter_riverpod_mvvm