Riverpod: Notifier
Coddy Flutter 여정의 상태 관리 섹션에 포함된 레슨. 27개 중 19번째.
숫자 하나에는 StateProvider를 사용해도 괜찮습니다. 상태에 규칙이 따를 때, 예를 들어 추가 및 제거 메서드가 있는 목록이라면 Notifier를 작성하세요. 상태와 상태를 변경하는 메서드를 담는 클래스입니다.
class GuestList extends Notifier<List<String>> {
@override
List<String> build() => [];
void add(String name) {
state = [...state, name];
}
}
final guestsProvider =
NotifierProvider<GuestList, List<String>>(GuestList.new);build는 첫 번째 상태인 빈 목록을 반환합니다. 클래스 내부에서 state는 현재 값입니다. GuestList.new는 클래스의 생성자이며, 공급자에 전달되어 notifier를 생성할 수 있게 합니다.
핵심 규칙은 다음과 같습니다. state에 새 값을 할당하고, 기존 값을 절대 변경하지 마세요. Riverpod은 state가 다른 객체로 설정될 때만 위젯에 알립니다. state.add(name)은 목록을 제자리에서 변경하므로 state는 여전히 같은 목록이고 아무도 변경 사실을 알지 못합니다. [...state, name]은 새 목록을 만듭니다. 세 개의 점은 기존의 모든 이름을 새 목록에 펼쳐 넣고, 그다음 새 이름을 맨 끝에 추가합니다.
위젯은 notifier를 통해 메서드를 호출합니다. ref.read(guestsProvider.notifier).add('Ada'). 이 페이지는 텍스트 컨트롤러도 유지하므로 상태를 가지는 종류인 ConsumerStatefulWidget입니다. 이 위젯의 State에는 필드로 ref가 있습니다.
챌린지
어려움방명록에 guestsProvider의 이름이 표시되지만, Add는 입력란을 비우기만 합니다.
GuestList에add(String name)메서드를 추가하고,state를 이름이 끝에 추가된 새 목록으로 설정합니다.- 입력란을 비우기 전에
Add가 입력란의 텍스트를 인수로 이 메서드를 호출하게 합니다.
직접 해보기
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class GuestList extends Notifier<List<String>> {
@override
List<String> build() => [];
}
final guestsProvider = NotifierProvider<GuestList, List<String>>(GuestList.new);
void main() {
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: PartyPage(),
);
}
}
class PartyPage extends ConsumerStatefulWidget {
const PartyPage({super.key});
@override
ConsumerState<PartyPage> createState() => _PartyPageState();
}
class _PartyPageState extends ConsumerState<PartyPage> {
final controller = TextEditingController();
@override
Widget build(BuildContext context) {
final guests = ref.watch(guestsProvider);
return Scaffold(
appBar: AppBar(title: Text('Guests: ${guests.length}')),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(16),
child: Row(
children: [
Expanded(
child: TextField(
controller: controller,
decoration: const InputDecoration(labelText: 'Guest name'),
),
),
const SizedBox(width: 8),
ElevatedButton(
onPressed: () {
controller.clear();
},
child: const Text('Add'),
),
],
),
),
Expanded(
child: ListView(
children: [
for (final name in guests) ListTile(leading: const Icon(Icons.person), title: Text(name)),
],
),
),
],
),
);
}
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
상태 관리의 모든 레슨
직접 연습해 보세요: 온라인 Flutter 컴파일러