이 코드는 Flutter Riverpod에서 StateNotifier와 StateNotifierProvider를 사용해 상태를 관리하는 방법을 보여줍니다. 이를 자세히 분석해 보겠습니다.
코드 구조
import 'package:flutter_riverpod/flutter_riverpod.dart';
// 상태 로직을 관리하는 클래스
class CounterNotifier extends StateNotifier<int> {
CounterNotifier() : super(0); // 초기 상태 설정
void increment() => state++; // 상태를 증가
void decrement() => state--; // 상태를 감소
}
// StateNotifierProvider 생성
final counterNotifierProvider =
StateNotifierProvider<CounterNotifier, int>((ref) => CounterNotifier());
1. CounterNotifier 클래스
CounterNotifier는 상태를 관리하기 위해 StateNotifier를 상속받아 만든 클래스입니다.
StateNotifier
- Riverpod에서 상태를 관리하는 클래스입니다.
- 제네릭 타입 <int>는 관리할 상태의 데이터 타입을 나타냅니다. 이 코드에서는 int 타입의 카운터 값을 관리합니다.
CounterNotifier 클래스 생성자:
- super(0)은 StateNotifier의 초기 상태를 설정합니다.
- 초기 상태는 0입니다.
state:
- 현재 상태를 나타냅니다. state를 읽거나 직접 변경할 수 있습니다.
- 여기서는 카운터 값(int)이 state에 저장됩니다.
ioncrement()와 decrement():
- 상태를 업데이트하는 메서드입니다.
- state++와 state--로 값을 증가하거나 감소시킵니다.
- state 값이 변경되면 Riverpod은 이를 구독하는 위젯을 자동으로 재빌드합니다.
2. StateNotifierProvider
final counterNotifierProvider =
StateNotifierProvider<CounterNotifier, int>((ref) => CounterNotifier());
StateNotifierProvider 설명
- StateNotifierProvider는 StateNotifier를 Riverpod에서 사용할 수 있도록 감싸는 역할을 합니다.
- 두 가지 타입을 받습니다: CounterNotifier(상태 로직을 정의한 클래스), int (관리되는 상태의 데이터 타입)
생성 방식
- (ref) => CounterNotifier():
- ref를 사용해 다른 Provider를 참조하거나, 의존성을 주입할 수 있습니다.
- 이 경우, 단순히 새로운 CounterNotifier 객체를 반환합니다.
StateNotifierProvider를 사용하는 이유
1. 상태 관리 로직 분리:
- 상태를 관리하는 로직(CounterNotifier)과 UI 코드가 분리되어 유지보수가 쉬워집니다.
2. 상태 변화 감지:
- 상태가 변경되면 Riverpod이 이를 구독하는 UI를 자동으로 재빌드합니다.
3. 복잡한 상태 관리:
- 단순한 숫자 증가/감소 외에도 더 복잡한 상태 관리 로직(예: API 호출, 데이터 처리 등)을 쉽게 확장할 수 있습니다.
3. UI와 연결
이제 이 Provider를 실제 UI에서 사용하는 방법을 살펴보겠습니다.
UI 구현
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
// 위에서 정의한 CounterNotifierProvider 가져오기
final counterNotifierProvider =
StateNotifierProvider<CounterNotifier, int>((ref) => CounterNotifier());
class CounterApp extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
// Provider로부터 상태 읽기
final counter = ref.watch(counterNotifierProvider);
return Scaffold(
appBar: AppBar(title: const Text('Counter with StateNotifier')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Counter: $counter', style: const TextStyle(fontSize: 24)),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () =>
ref.read(counterNotifierProvider.notifier).decrement(),
child: const Text('-'),
),
const SizedBox(width: 16),
ElevatedButton(
onPressed: () =>
ref.read(counterNotifierProvider.notifier).increment(),
child: const Text('+'),
),
],
),
],
),
),
);
}
}
UI 동작 설명
1. 상태 읽기:
final counter = ref.watch(counterNotifierProvider);
- ref.watch()로 counterNotifierProvider의 상태(int)를 읽습니다.
- 이 값은 UI에서 카운터를 표시하는 데 사용됩니다.
2. 상태 업데이트:
ref.read(counterNotifierProvider.notifier).increment();
- ref.read()로 CounterNotifier 인스턴스에 접근
- increment()와 decrement()를 호출하여 상태를 변경
3. UI 자동 갱신:
- 상태가 변경되면 Riverpod은 자동으로 UI를 재빌드하여 새로운 상태를 반영합니다.
4. StateNotifier와 StateProvider의 차이점
특징 | StateNotifier | StateProvider |
용도 | 복잡한 상태 로직 관리 | 간단한 상태 로직 관리 |
상태 로직 분리 | 상태 관리 로직을 별도 클래스로 정의 | 상태 로직이 Provider 내부에 정의 |
확장 가능성 | 확장성이 높음(추가 메서드, 복잡한 로직 구현 가능) | 단순 상태 업데이트에 적합 |
테스트 용이성 | 상태 로직을 테스트하기 용이 | 간단한 상태 테스트에 적합 |
5. 활용 예시
CounterNotifier는 간단한 카운터 예제이지만, 이 구조는 더 복잡한 상태를 관리할 때도 유용합니다. 예를 들어:
1. 리스트 관리: 아이템 추가/삭제/필터링.
2. 비동기 작업: API 호출 후 상태 업데이트.
3. 여러 상태의 조합: 다양한 상태를 조합하여 계산된 상태를 제공.
6. 결론
이 코드는 StateNotifier와 StateNotifierProvider를 사용해 상태를 명확히 관리하는 방법을 보여줍니다.
이를 활용하면 상태 관리 로직을 재사용 가능하고 테스트하기 쉬운 구조로 설계할 수 있습니다.
위 코드를 직접 실행하며 Riverpod의 강력함을 체감해보세요! 😊
'IT > flutter' 카테고리의 다른 글
[flutter] Container위젯과 DecoratedBox 위젯의 효율적인 사용 (0) | 2025.01.23 |
---|---|
[상태관리] flutter Riverpod을 이용하여 todo 리스트 만들어 보기 (0) | 2024.12.19 |
[상태관리] Riverpod - FutureProvider 비동기 데이터 관리 (0) | 2024.12.19 |
[상태관리]Riverpod의 WidgetRef 객체 (0) | 2024.12.19 |
[flutter] Riverpod으로 상태 관리 시작하기: 초보자를 위한 단계별 가이드 (0) | 2024.12.19 |