CodeGenerator를 통해 provider를 생성하며 해당 provider들의 생성 및 dispose에 대해서 알아보자
provider는 여러가지 기준으로 분류할 수 있다.
분류의 기준 중 하나로 [ 함수 / 클래스 ] 가 있다.
이번 글에서는 함수형 provider들의 생성 및 사용에 대하여 기술한다.
0. observer
프로바이더들의 생성 및 변경, 삭제 이벤트를 확인하기 위해 observer를 등록하여 로그를 찍도록 하였다.
ProviderObserver 객체를 상속받아 원하는 형태로 사용 가능하며, 용도에 따라서 여러 observer를 추가하여 사용할 수 있다.
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:logger/logger.dart';
class CustomProviderObserver extends ProviderObserver {
@override
void didDisposeProvider(ProviderBase<Object?> provider, ProviderContainer container) {
Logger().i("${provider.name} is disposed : ${provider.runtimeType}");
super.didDisposeProvider(provider, container);
}
@override
void didAddProvider(ProviderBase<Object?> provider, Object? value, ProviderContainer container) {
Logger().i("${provider.name} is add : ${provider.runtimeType} , $value ");
super.didAddProvider(provider, value, container);
}
@override
void didUpdateProvider(
ProviderBase<Object?> provider, Object? previousValue, Object? newValue, ProviderContainer container) {
Logger().i("${provider.name} is update : $newValue");
super.didUpdateProvider(provider, previousValue, newValue, container);
}
}
ProviderScope getRiverpodMain() {
return ProviderScope(
observers: [CustomProviderObserver()],
child: const MaterialApp(
home: RiverpodMain(),
),
);
}
1. provider
가장 기본적인 형태의 provider 이며 값을 반환한다. 일정한 값을 반환하는 역할만을 수행한다.
리버팟의 생명주기에 따라 캐싱되고 삭제(dispose) 시킨다
part 'provider.g.dart';
@riverpod
String singleValue(Ref ref) {
return "This is Value";
}
dio, retrofit 클래스와 같이 전역적으로 사용하는 특정 객체를 등록하여 사용하기도 한다.
I/flutter ( 6447): ┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
I/flutter ( 6447): │ #0 CustomProviderObserver.didAddProvider (package:state_management_practice/riverpod/riverpod/obserber/riverpod_observer.dart:13:14)
I/flutter ( 6447): │ #1 runTernaryGuarded (package:riverpod/src/run_guarded.dart:44:7)
I/flutter ( 6447): ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
I/flutter ( 6447): │ 💡 singleValueProvider is add : AutoDisposeProvider<String> , This is Value
I/flutter ( 6447): └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
해당 프로바이더는 watch 하여 사용하는 경우 위와 같이 add 이벤트가 발생하는 것을 확인할 수 있다.
I/flutter ( 6447): ┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
I/flutter ( 6447): │ #0 CustomProviderObserver.didDisposeProvider (package:state_management_practice/riverpod/riverpod/obserber/riverpod_observer.dart:7:14)
I/flutter ( 6447): │ #1 runBinaryGuarded (package:riverpod/src/run_guarded.dart:29:7)
I/flutter ( 6447): ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
I/flutter ( 6447): │ 💡 singleValueProvider is disposed : AutoDisposeProvider<String>
I/flutter ( 6447): └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
기본적으로 프로바이더는 필요할 때 생성되며, 필요없다고 판단되면 삭제된다.
watch 혹은 read하면 그때 생성되며, watch하는 곳이 없을 시 자동으로 삭제된다(auto dispose)
만약 자동으로 삭제되면 안된다면 해당 옵션을 제외하여야 한다.
이러한 속성은 모든 provider 공통이다.
추가로 provider호출 시 인자를 추가할 수 있다.
생성 시 다음과 같이 추가할 인자를 명시하고 호출 시 입력하면 된다.
@riverpod
String singleValueWithParam(Ref ref, {required int param}) {
return "This is Value and param is $param";
}
class _ValueWithParamTestScreen extends ConsumerWidget {
const _ValueWithParamTestScreen({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final value = ref.watch(singleValueWithParamProvider(param: 512));
return Scaffold(
appBar: AppBar(title: const Text("value")),
body: Center(
child: Text(value),
),
);
}
}
2. FutureProvider
Futurue<>를 반환값으로 명시하는 경우 자동으로 FutureProvider로 생성된다.
Futrue를 반환하는 provider 가 아닌 AutoDisposeFutureProvider를 반환한다.
@riverpod
Future<String> futureValue(Ref ref) async {
return Future.delayed(
const Duration(milliseconds: 500),
() => "Future is here",
);
}
class _FutureScreen extends ConsumerWidget {
const _FutureScreen({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final value = ref.watch(futureValueProvider);
return Scaffold(
appBar: AppBar(
title: const Text("future"),
),
body: value.when(
data: (data) => Center(
child: Text(data),
),
error: (error, stackTrace) => Text(error.toString()),
loading: () => const Center(child: CircularProgressIndicator()),
),
);
}
}
when 옵션을 사용하여 loading, error, success 상태를 모두 관리 가능하다.
Code Generation 알아보기 | Riverpod
Code Generation 알아보기 | Riverpod
Code generation is the idea of using a tool to generate code for us.
docs-v2.riverpod.dev
BowonLee/state_management_practice: 상태관리 라이브러리 관련 학습 (github.com)
GitHub - BowonLee/state_management_practice: 상태관리 라이브러리 관련 학습
상태관리 라이브러리 관련 학습. Contribute to BowonLee/state_management_practice development by creating an account on GitHub.
github.com
'flutter' 카테고리의 다른 글
Flutter 유닛테스트 기본 사용방법과 예시 (0) | 2023.05.29 |
---|---|
riverpod2.0 codegeneration 학습 2 (1) | 2023.05.06 |
리버팟 2.0 간단한 공부 정리 (0) | 2023.04.23 |
Bloc을 활용한 UI 전반의 설정과 변경 (0) | 2023.03.04 |
Flutter Hive 사용하기 (+Freezed) (0) | 2023.01.09 |