riverpod annotation
| topics | 500-모바일개발 501 Flutter 504 Riverpod |
| types | 실습 레퍼런스 |
| tags | |
| references | codewithandrea.com/articles/flutter-r... q.agency/blog/migrating-from-statenot... riverpod.dev/docs/concepts/about_code... |
Riverpod Annotation
Riverpod 2.0에서 추가된 어노테이션 기반 코드 생성 방식이다.
설치
dependencies:
flutter_riverpod: ^2.4.0
riverpod_annotation: ^2.3.0
dev_dependencies:
riverpod_generator: ^2.3.0
build_runner: ^2.4.0
기본 Provider
이전 방식
final helloProvider = Provider<String>((ref) {
return 'Hello';
});
어노테이션 방식
part 'hello.g.dart';
@riverpod
String hello(HelloRef ref) {
return 'Hello';
}
장점: 타입 추론이 자동으로 되고, 코드가 더 간결하다.
Family Provider
파라미터를 받는 Provider다.
이전 방식
final movieProvider = FutureProvider.family<Movie, int>((ref, movieId) async {
return ref.watch(moviesRepositoryProvider).movie(movieId: movieId);
});
어노테이션 방식
@riverpod
Future<Movie> movie(MovieRef ref, {required int movieId}) {
return ref.watch(moviesRepositoryProvider).movie(movieId: movieId);
}
왜 이게 좋냐면: family를 명시적으로 작성할 필요가 없다. 파라미터가 있으면 자동으로 family provider로 생성된다.
Notifier
상태를 변경하는 Provider다.
이전 방식
final counterProvider = NotifierProvider<CounterNotifier, int>(() {
return CounterNotifier();
});
class CounterNotifier extends Notifier<int> {
@override
int build() => 0;
void increment() => state++;
}
어노테이션 방식
part 'counter.g.dart';
@riverpod
class Counter extends _$Counter {
@override
int build() => 0;
void increment() => state++;
}
AsyncNotifier
비동기 상태를 다루는 Notifier다.
@riverpod
class UserNotifier extends _$UserNotifier {
@override
Future<User> build() async {
return await ref.watch(userRepositoryProvider).getCurrentUser();
}
Future<void> updateName(String name) async {
state = const AsyncValue.loading();
state = await AsyncValue.guard(() async {
final user = state.value!;
final updated = user.copyWith(name: name);
await ref.read(userRepositoryProvider).update(updated);
return updated;
});
}
}
keepAlive
Provider가 dispose되지 않도록 유지한다.
@Riverpod(keepAlive: true)
Future<Database> database(DatabaseRef ref) async {
return await openDatabase();
}
코드 생성
# <span id="한번만-빌드"></span>한번만 빌드
dart run build_runner build
# <span id="파일-변경-감지"></span>파일 변경 감지
dart run build_runner watch
# <span id="충돌-해결"></span>충돌 해결
dart run build_runner build --delete-conflicting-outputs
테스트
void main() {
test('counter increments', () {
final container = ProviderContainer();
addTearDown(container.dispose);
expect(container.read(counterProvider), 0);
container.read(counterProvider.notifier).increment();
expect(container.read(counterProvider), 1);
});
}
관련 문서
- riverpod read listen - watch/read/listen 차이
- freezed,JsonSerialiable - 코드 생성 도구
- live templete - 템플릿으로 빠르게 작성