Riverpod 라이브러리를 이용한 상태관리 방법에 대해 알아보고 적어둔다.
Provider는 상태를 저장하고, 자손 위젯에서 상태에 접근할 수 있도록 제공해주는 InheritedWidget를 래핑한 라이브러리이다. Provider 개발자가 단점을 보완하여 재작성된 라이브러리가 Riverpod 상태 관리 라이브러리이다.
1. 먼저 https://pub.dev/packages/riverpod 사이트에서 flutter_riverpod 의 최신버전을 확인하여 pubspec.yaml 에 추가한다.
name: riverpod_ex
description: A new Flutter project.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1
environment:
sdk: '>=3.1.5 <4.0.0'
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
flutter_riverpod: ^2.4.8
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
flutter:
uses-material-design: true
|
2. main.dart 파일에서 아래와 같이
_MyApp을 ProviderScope 로 감싸준다.
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_ex/screen/home_screen.dart';
void main() {
runApp(ProviderScope(
child: _MyApp(),
));
}
class _MyApp extends StatelessWidget {
const _MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: HomeScreen(),
);
}
}
|
3. state_provider.dart
상태관리를 할 StateProvider를 구현한다.
import 'package:flutter_riverpod/flutter_riverpod.dart';
final numberProvider = StateProvider<int>((ref) => 0);
|
4.state_provider_screen.dart
ConsumerWidget 을 상속하고, Widget build(BuildContext context) 를 Widget build(BuildContext context, WidgetRef ref) 로 변경해준다.
Riverpod에서 정의된 추상클래스 WidgetRef를 통해서 Provider에 접근 가능하고,
ref.watch를 통해서 변경을 감지하면 해당 위젯을 다시 build한다.
final provider = ref.watch(numberProvider); 를 추가하여 상태 변화를 감지한다.
Provider의 값이 변경되면 자체적으로 다시 build된다.
WidgetRef의 read 메소드를 호출(Provider의 값을 읽어오기만 함)하며, 상태를 변경할 StateProvider의 notifier를 전달한다.
ref.read(numberProvider.notifier).update((state) => state + 1); 로 상태를 증가시키거나,
ref.read(numberProvider.notifier).state = ref.read(numberProvider.notifier).state - 1; 와 같은 방법으로 상태를 감소/증가 시킬 수 있다.
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../layout/default_layout.dart';
import '../riverpod/state_provider.dart';
class StateProviderScreen extends ConsumerWidget {
const StateProviderScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final provider = ref.watch(numberProvider);
return DefaultLayout(
title: 'Basic Provider',
body: SizedBox(
width: MediaQuery.of(context).size.width,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
provider.toString(),
textAlign: TextAlign.center,
),
ElevatedButton(
onPressed: () {
ref.read(numberProvider.notifier).update((state) => state + 1);
},
child: Text('UP'),
),
ElevatedButton(
onPressed: () {
ref.read(numberProvider.notifier).state =
ref.read(numberProvider.notifier).state - 1;
},
child: Text(
'DOWN',
),
),
ElevatedButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (_) => _NextScreen()),
);
},
child: Text(
'Next Screen',
),
),
],
),
),
);
}
}
class _NextScreen extends ConsumerWidget {
const _NextScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final provider = ref.watch(numberProvider);
return DefaultLayout(
title: 'Basic Provider',
body: SizedBox(
width: MediaQuery.of(context).size.width,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
provider.toString(),
textAlign: TextAlign.center,
),
ElevatedButton(
onPressed: () {
ref.read(numberProvider.notifier).update((state) => state + 1);
},
child: Text('UP'),
),
],
),
),
);
}
}
|
'Flutter 앱 > 상태관리' 카테고리의 다른 글
Flutter Riverpod - NotifierProvider.family (0) | 2023.12.11 |
---|---|
Flutter Riverpod - NotifierProvider (0) | 2023.12.11 |
Flutter GetX (반응형 상태관리) (0) | 2022.06.24 |
Flutter GetX (단순 상태관리) (0) | 2022.06.23 |
Flutter Provider (상태관리) (0) | 2022.06.21 |