: 경랑화된 상태관리 라이브러리
등 여러 이유가 존재한다.
final exampleProvider = Provider<int>((ref) => 100);
final
사용void main() {
runApp(ProviderScope(child: MyApp());
}
Provider의 데이터를 사용하기 위해서는 두가지 방법이 존재
Consumer
위젯 사용final myValueProvider = Provider<int>((ref) {
return 100;
});
class HomePage extends StatelessWidget {
const HomePage({super.key});
Widget build(BuildContext context) {
return Scaffold(
body: Consumer( // <==
builder: (context, ref, child) {
final value = ref.watch(myValueProvider);
return Text(value.toString());
},
),
);
}
}
Consumer
위젯으로 감싼 형태로 구현builder
라는 매개 변수 존재value
(= myValueProvider)가 변경될 때 마다 Consumer
위젯 내부에 있는 위젯만 새로 빌드되고, 나머지 위젯은 그대로 유지ConsumerWidget
을 StatelessWidget 대신 사용final myValueProvider = Provider<int>((ref) {
return 100;
});
class HomePage extends ConsumerWidget {
const HomePage({super.key});
Widget build(BuildContext context, WidgetRef ref) {
final value = ref.watch(myValueProvider);
return Scaffold(
appBar: AppBar(
title: const Text('Riverpod'),
),
body: Center(
child: Text(
value.toString(),
style: Theme.of(context).textTheme.headline2,
),
),
);
}
}
Consumer
위젯으로 상태 변경을 하고 싶은 위젯을 감싸는 대신, 위젯 자체를 ConsumerWidget
으로 변경하여 Consumer
위젯과 동일하게 기능 작동ConsumerWidget
== StatelessWidget
+ Provider 사용예시
class HomePage extends ConsumerWidget {
const HomePage({super.key});
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
appBar: AppBar(
title: const Text('Riverpod'),
),
body: Center(
child: GestureDetector(
onTap: () {
ref.read(loginRepository.notifier).login();
},
child: Text(
value.toString(),
style: Theme.of(context).textTheme.headline2,
),
),
),
);
}
}
ref
는 다른 프로바이더를 가지고 있을 수 있음final helloStringProvider = StateProvider<String>((ref) {
return 'Hello';
});
final worldStringProvider = StateProvider<String>((ref) {
return 'World';
});
final helloWorldStringProvider = Provider<String>((ref) {
final hello = ref.watch(helloStringProvider); // obtaining the helloStringProvider value inside this provider.
final world= ref.watch(worldStringProvider); // obtaining the worldStringProvider value inside this provider.
return '$hello$world';
});
class HomePage extends ConsumerWidget {
const HomePage({super.key});
Widget build(BuildContext context, WidgetRef ref) {
final value = ref.watch(helloWorldStringProvider);
return Scaffold(
appBar: AppBar(
title: const Text('Riverpod'),
),
body: Center(
child: Text(
value,
style: Theme.of(context).textTheme.headline2,
),
),
);
}
}
ref.listen()
은 operation을 수행 또는 함수를 호출할 때 사용 (ref.watch()
는 listen하고 있는 porivder가 변경되었을 때 위젯과 provider를 재빌드)final numberProvider = StateProvider<num>((ref) {
return 1;
});
class HomePage extends ConsumerWidget {
const HomePage({super.key});
Widget build(BuildContext context, WidgetRef ref) {
final value = ref.watch(numberProvider);
ref.listen(helloStringProvider, (previousValue, newValue) {
log('Number Changed: $newValue');
});
return Scaffold(
appBar: AppBar(
title: const Text('Riverpod'),
),
body: Center(
child: Text(
value.toString(),
style: Theme.of(context).textTheme.headline2,
),
),
);
}
}
read
, watch
, listen
사용법ref.read()
은 reactive하지 않기 때문에 사용을 최대한 피하는 것이 좋음. ref.read()
, ref.listen()
을 사용하는 것 보다 ref.watch()
를 사용하는 것을 더욱 선호ref.watch()
와 동일하게 비동기적으로 처리x, initState 또는 state 라이프사이클 내부에서 사용해서는 안됨