Menu
CoddyTech

여러 모델: MultiProvider

Coddy Flutter 여정의 상태 관리 섹션에 포함된 레슨. 27개 중 15번째.

각 모델은 한 가지에만 집중하도록 하세요. 한 클래스에는 점수를, 다른 클래스에는 생명을 둡니다. 작은 모델은 읽기 쉽고, 위젯은 필요한 항목만 관찰합니다. 모델이 여러 개인 앱에는 프로바이더도 여러 개 필요합니다.

프로바이더를 중첩해 하나를 다음 프로바이더의 자식으로 둘 수도 있지만, 모델이 하나씩 늘어날 때마다 코드가 오른쪽으로 밀립니다. MultiProvider는 대신 평평한 목록을 사용합니다.

runApp(
  MultiProvider(
    providers: [
      ChangeNotifierProvider(create: (context) => Score()),
      ChangeNotifierProvider(create: (context) => Lives()),
    ],
    child: const MyApp(),
  ),
);

목록에 있는 프로바이더에는 각자의 child가 없습니다. MultiProvider가 프로바이더를 쌓고 모든 프로바이더 아래에 child를 배치합니다. 아래에 있는 모든 위젯은 각 모델의 타입을 지정해 해당 모델을 관찰하거나 읽을 수 있습니다. 예를 들면 context.watch<Lives>()입니다.

challenge icon

챌린지

쉬움

게임 페이지는 두 모델인 Score와 Lives를 감시하지만, main은 점수만 제공하므로 앱에 오류가 표시됩니다.

  • main의 provider를 두 모델을 모두 제공하는 MultiProvider로 바꾸세요.

직접 해보기

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class Score extends ChangeNotifier {
  int _points = 0;

  int get points => _points;

  void hit() {
    _points += 10;
    notifyListeners();
  }
}

class Lives extends ChangeNotifier {
  int _left = 3;

  int get left => _left;

  void miss() {
    if (_left > 0) {
      _left--;
      notifyListeners();
    }
  }
}

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => Score(),
      child: const MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: GamePage(),
    );
  }
}

class GamePage extends StatelessWidget {
  const GamePage({super.key});

  @override
  Widget build(BuildContext context) {
    final points = context.watch<Score>().points;
    final lives = context.watch<Lives>().left;
    return Scaffold(
      appBar: AppBar(title: Text('Lives: $lives')),
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text('Points: $points', style: const TextStyle(fontSize: 40)),
            const SizedBox(height: 16),
            Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                ElevatedButton(
                  onPressed: () => context.read<Score>().hit(),
                  child: const Text('Hit'),
                ),
                const SizedBox(width: 16),
                ElevatedButton(
                  onPressed: () => context.read<Lives>().miss(),
                  child: const Text('Miss'),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}
quiz icon실력 점검

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

상태 관리의 모든 레슨

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