상태를 어디에 둘지 선택하기
Coddy Flutter 여정의 상태 관리 섹션에 포함된 레슨. 27개 중 21번째.
Settings 화면의 다크 모드 스위치는 움직이지만, 아무것도 어두워지지 않습니다. setState로 값을 유지하지만, 스위치만 그 값을 볼 수 있습니다. 테마는 멀리 떨어진 MyApp에서 설정됩니다. 이 값은 앱 전체에 속합니다.
앱의 모든 값에는 자리가 필요합니다. 누가 그 값을 사용하는지 생각해 보세요.
- 하나의 위젯(필드의 텍스트, 열린 패널, 탭 인덱스): 해당 위젯에서
setState를 사용합니다. - 가까이 있는 몇 개의 위젯(버튼과 그 옆의 레이블): 부모 위젯으로 올리고 아래로 전달합니다.
- 여러 위젯 또는 여러 화면(사용자, 장바구니, 설정): Provider 또는 Riverpod를 사용하는 공유 모델입니다.
Provider와 Riverpod 중 무엇을 선택할까요? 둘 다 제 역할을 합니다. Provider는 조금 더 간단하고 위젯 트리에 모델을 넣어 context를 통해 찾습니다. Riverpod는 트리 바깥에 프로바이더를 두므로 값에 context가 필요 없고, 프로바이더끼리 서로 감시할 수 있습니다. 앱 하나를 선택해 어디서나 동일하게 사용하세요.
여기에는 StateProvider가 적합합니다. 하나의 bool 값을 MyApp에서 읽어 테마를 선택하고, 스위치에서 값을 변경합니다.
final darkModeProvider = StateProvider((ref) => false);
// MyApp에서, 이제 ConsumerWidget:
themeMode: ref.watch(darkModeProvider) ? ThemeMode.dark : ThemeMode.light,챌린지
어려움다크 모드 스위치가 앱 전체에 적용되도록 하세요.
- 맨 위에
final darkModeProvider = StateProvider((ref) => false);를 추가하세요. MyApp을ConsumerWidget으로 바꾸고,themeMode가 프로바이더를 따르도록 하세요.SettingsScreen을ConsumerWidget으로 바꾸세요. 스위치에는 프로바이더의 값이 표시되고, 값이 변경되면 해당 값이 설정됩니다.
직접 해보기
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() {
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData.light(),
darkTheme: ThemeData.dark(),
themeMode: ThemeMode.light,
home: const HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Notes'),
actions: [
IconButton(
icon: const Icon(Icons.settings),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SettingsScreen()),
);
},
),
],
),
body: const Center(child: Text('No notes yet')),
);
}
}
class SettingsScreen extends StatefulWidget {
const SettingsScreen({super.key});
@override
State<SettingsScreen> createState() => _SettingsScreenState();
}
class _SettingsScreenState extends State<SettingsScreen> {
bool dark = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Settings')),
body: ListView(
children: [
SwitchListTile(
title: const Text('Dark mode'),
value: dark,
onChanged: (value) {
setState(() {
dark = value;
});
},
),
],
),
);
}
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
상태 관리의 모든 레슨
직접 연습해 보세요: 온라인 Flutter 컴파일러