728x90
Riverpod
Riverpod이란?
- flutter의 강력한 상태 관리 라이브러리
- Provider의 단점을 개선
- MVVM 아키텍처에서 ViewModel을 쉽게 구현할 수 있고, View에서 ViewModel의 관찰을 쉽게 하게 해줌
Riverpod의 주요 특징
- 타입 안전성 및 컴파일 타임 오류 감지
- 반응형 상태 관리 : 데이터 변경 시 UI 자동 업데이트 및 불필요한 리빌드 방지
- 의존성 주입 : Provider를 통해 여러 곳에서 동일한 인스턴스 공유 가능
- 데이터 캐싱 및 API 관리 : 원격 데이터 소스를 효율적으로 가져옴
- 전역 접근 가능 : context 없이도 어디서든 상태에 접근 가능
- 테스트 친화적
Provider와 Notifier
Provider 종류
Provider 종류 | 특징 | 사용 예시 |
Provider | 읽기 전용 데이터 제공 (상태 변경 X) | 상수 데이터, 계산된 값 전달 |
StateProvider | 간단한 상태 변경 관리 (int, bool 등) | Counter, ON/OFF 버튼 |
FutureProvider | 비동기 데이터 관리 (API 요청 등) | 서버 통신, 데이터 로드 |
StreamProvider | 실시간 스트림 데이터 관리 | WebSocket, 채팅 |
NotifierProvider | 복잡한 상태 관리 (MVVM의 ViewModel에 적합) | CRUD, 데이터 가공 로직 |
AutoDispose | 위 Provider에 .autoDispose 추가 가능 (메모리 절약) | 일회성 데이터 로드, 화면 전환 시 데이터 해제 |
Notifier 종류
Notifier는 NotifierProvider와 함께 사용하여 복잡한 상태관리 가능. 상태 클래스 선언이 가능하고, UI 업데이트, 데이터 처리에 최적화
Notifier 종류 | 특징 | 사용 예시 |
Notifier | 일반 상태 관리 도구 (싱글톤 구조) | 복잡한 상태 로직 |
AsyncNotifier | 비동기 상태 관리 도구 | API 호출, 데이터 로드 |
AutoDisposeNotifier | 화면 종료 시 자동 해제 | 화면이 바뀌는 경우 메모리 절약 |
AutoDisposeAsyncNotifier | 비동기 상태 + 자동 해제 관리 | 일회성 비동기 작업 (예: 검색 결과) |
FamilyNotifier | 매개변수를 받는 Notifier | 사용자 ID 기반 데이터 로드 |
AutoDisposeFamilyNotifier | 매개변수 + 자동 해제 관리 | 사용자 ID별 비동기 데이터 로드 |
예시 코드
FutureProvider(비동기 데이터 관리)
// 비동기 String 타입의 데이터를 관리하는 weatherProvider 정의
final weatherProvider = FutureProvider<String>((ref) async {
await Future.delayed(Duration(seconds: 2)); // 2초 딜레이 후 데이터 반환
return "맑음"; // "맑음" 이라는 문자열 데이터 반환
});
class WeatherScreen extends ConsumerWidget { // ComsumerWidget : Riverpod의 상태 관리 구독
@override
Widget build(BuildContext context, WidgetRef ref) { //WidgetRef ref를 통해 Provider 상태에 접근 가능
// weatherProvier의 상태 변화를 감지하고 자동을 화면을 리빌드
// FutureProvider는 비동기 상태라 AsyncValue 타입의 데이터 반환
final weatherState = ref.watch(weatherProvider);
return Scaffold(
appBar: AppBar(title: Text('FutureProvider 예제')),
// when()은 AsyncValue에서 제공하는 메서드, 비동기 상태에 따라 UI를 다르게 표시할 수 있음
body: weatherState.when(
data: (weather) => Center(child: Text('오늘의 날씨: $weather')), // 성공 시 데이터를 받아 화면에 표시
loading: () => Center(child: CircularProgressIndicator()), // 로딩 시 로딩 스피너 표시
error: (error, _) => Center(child: Text('에러 발생: $error')), // 에러 발생 시 에러 메세지 출력
),
);
}
}
NotifierProvier(복잡한 상태 관리)
// Notifier를 상속받아 상태 관리를 담당하는 ViewModel
class CounterNotifier extends Notifier<int> { // 상태의 데이터 타입 : int
@override
int build() => 0; // 0으로 초기화
// state는 현재 상태 값을 의미, Notifier에서 제공하는 기본 상태 관리 변수
// state 값이 변경되면 Notifier가 이를 감지하고 자동으로 UI 업데이트
void increment() => state++;
void decrement() => state--;
}
// counterProvider 정의
// 위에서 선언한 CounterNotifier를 통해 int 타입의 상태를 관리하는 Provier
// CounterNotifier.new를 통해 CounterNotifier의 인스턴스 생성
final counterProvider = NotifierProvider<CounterNotifier, int>(CounterNotifier.new);
// View(UI)
class CounterScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
// counterProvier의 상태(int)를 구독
// count의 값이 바뀔 때 마다 UI가 자동으로 빌드(ref.watch 특징)
final count = ref.watch(counterProvider);
return Scaffold(
appBar: AppBar(title: Text('NotifierProvider 예제')),
body: Center(child: Text('Count: $count')),
floatingActionButton: FloatingActionButton(
// 사용자가 버튼을 누르면 counterProvider.notifier(CounterNotifier)의 increment()가 호출됨
// 버튼을 누를 때마다 0에서부터 1씩 값이 증가
onPressed: () => ref.read(counterProvider.notifier).increment(),
child: Icon(Icons.add),
),
);
}
}
ref.watch()와 ref.read()
사용 방법 | 역할 | 사용 예시 |
ref.watch(provider) | 상태를 자동으로 구독하여 UI 업데이트 | UI에서 사용 (화면 리빌드 필요 시) |
ref.read(provider) | 상태를 한 번만 읽거나, .notifier 호출 시 사용 | 이벤트 핸들러, 버튼 클릭 시 |
ref.read(provider.notifier) | 상태를 변경할 때 사용, ref.read()에서만 사용 | 상태 변경 시 필수 |
'앱개발 > flutter' 카테고리의 다른 글
[Flutter] MVVM 아키텍처(Model-View-ViewModel) (0) | 2025.03.23 |
---|---|
[Flutter] JSON, jsonEncode(toJson), jsonDecode(fromJson) (2) | 2025.03.21 |
[Flutter] TextField, TextFormField, TextEditingController (0) | 2025.03.20 |
[Flutter] 레이아웃 관련 위젯(2) : Row, Column, Stack (2) | 2025.03.19 |
[Flutter] 레이아웃 관련 위젯(1) : Container, SizedBox, Card (0) | 2025.03.18 |