Menu
CoddyTech

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가 있습니다.

challenge icon

챌린지

어려움

방명록에 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)),
              ],
            ),
          ),
        ],
      ),
    );
  }
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

상태 관리의 모든 레슨

직접 연습해 보세요: 온라인 Flutter 컴파일러