setState 및 InheritedWidget
`setState`를 사용한 로컬 상태 관리의 기초를 익히고, 위젯 트리 아래로 데이터를 전달하는 `InheritedWidget`의 개념을 이해합니다.
setState 및 InheritedWidget은(는) CoddyKit의 무료 Flutter Mobile Development 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Flutter Mobile Development 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Flutter Mobile Development 강의에는 총 4개의 강의가 포함되어 있습니다.
이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.
What is State Management?
In Flutter, 'state' refers to any data that can change during the lifetime of a widget. This could be a counter value, user input, or data fetched from the internet.
Managing this changing data, or 'state,' is crucial for building dynamic and interactive mobile applications. We need ways to update the UI when data changes.
Local State with setState
For changes that only affect a single widget, or a small, self-contained part of it, setState is your primary tool. It's used within a StatefulWidget.
Calling setState(() { ... }); tells Flutter that the internal state of this widget has changed and that it needs to rebuild its UI to reflect the new data.
setState in Action: Counter App
Let's build a simple counter. Notice how calling _incrementCounter() updates the _counter variable inside setState, which then triggers the UI to rebuild and show the new count.
import 'package:flutter/material.dart';
class MyCounterApp extends StatefulWidget {
@override
_MyCounterAppState createState() => _MyCounterAppState();
}
class _MyCounterAppState extends State<MyCounterApp> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('setState Counter')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('You have pushed the button this many times:'),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
void main() {
runApp(MaterialApp(home: MyCounterApp()));
}How setState Triggers Rebuilds
When setState is called, Flutter marks the StatefulWidget as 'dirty' and schedules a rebuild for that widget and its descendants.
Crucially, setState only rebuilds the part of the widget tree rooted at the StatefulWidget where it was called, not the entire application. This helps keep your UI updates efficient.
Limitations: The Problem of Prop Drilling
While setState is great for local state, it becomes cumbersome when you need to share state with widgets deep down the tree.
Passing data through many intermediate widgets that don't actually need it is called 'prop drilling'. It makes code harder to read, maintain, and refactor.
Introducing InheritedWidget
InheritedWidget is a special type of widget designed to efficiently pass data down the widget tree. Any child widget, no matter how deep, can access the data provided by an InheritedWidget.
This solves the 'prop drilling' problem by allowing widgets to 'inherit' data from their ancestors without explicit passing.
Building an InheritedWidget
To create an InheritedWidget, you extend the base class and define the data you want to share. It always requires a child widget, which is the subtree that can access its data.
child: The widget subtree wrapped by thisInheritedWidget.updateShouldNotify: A crucial method that tells Flutter if dependent widgets need to rebuild when theInheritedWidget's data changes.
import 'package:flutter/material.dart';
class MyThemeData extends InheritedWidget {
final Color primaryColor;
const MyThemeData({
Key? key,
required this.primaryColor,
required Widget child,
}) : super(key: key, child: child);
@override
bool updateShouldNotify(MyThemeData oldWidget) {
// Return true if the data has changed,
// so dependents rebuild.
return oldWidget.primaryColor != primaryColor;
}
}Accessing InheritedWidget Data
Child widgets retrieve data from an InheritedWidget using a static of(BuildContext context) method. This method efficiently searches up the widget tree for the nearest instance of the specified InheritedWidget.
The context.dependOnInheritedWidgetOfExactType method is commonly used within the of() method to establish a dependency.
import 'package:flutter/material.dart';
// Assume MyThemeData InheritedWidget is defined elsewhere.
// It needs a static 'of' method:
// static MyThemeData? of(BuildContext context) {
// return context.dependOnInheritedWidgetOfExactType<MyThemeData>();
// }
class MyColorDisplay extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Accessing the InheritedWidget's data using its 'of' method
final theme = MyThemeData.of(context);
return Text(
'Current color: ${theme?.primaryColor ?? 'Default'}' ,
style: TextStyle(color: theme?.primaryColor ?? Colors.black),
);
}
}Full InheritedWidget Example
Here's a complete example showing how MyThemeData provides a primary color to a deeply nested MyColorDisplay widget. Notice how MyColorDisplay accesses the data directly via MyThemeData.of(context).
import 'package:flutter/material.dart';
// 1. Our custom InheritedWidget
class MyThemeData extends InheritedWidget {
final Color primaryColor;
const MyThemeData({
Key? key,
required this.primaryColor,
required Widget child,
}) : super(key: key, child: child);
static MyThemeData? of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<MyThemeData>();
}
@override
bool updateShouldNotify(MyThemeData oldWidget) {
return oldWidget.primaryColor != primaryColor;
}
}
// 2. A widget that consumes the data
class MyColorDisplay extends StatelessWidget {
@override
Widget build(BuildContext context) {
final theme = MyThemeData.of(context);
return Container(
padding: EdgeInsets.all(16.0),
decoration: BoxDecoration(
color: theme?.primaryColor ?? Colors.grey,
borderRadius: BorderRadius.circular(8.0),
),
child: Text(
'Color Box',
style: TextStyle(color: Colors.white, fontSize: 18),
),
);
}
}
// 3. The main app structure
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('InheritedWidget App')),
body: MyThemeData( // Providing the theme data
primaryColor: Colors.deepPurple,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Data provided by InheritedWidget:'),
SizedBox(height: 20),
MyColorDisplay(), // This widget consumes the data
SizedBox(height: 20),
Text('This text is also a child.'),
],
),
),
),
),
);
}
}
void main() {
runApp(MyApp());
}setState vs. InheritedWidget
When to use which?
setState: Ideal for local, internal state changes within a singleStatefulWidget. Simple and direct.InheritedWidget: Best for sharing data efficiently with multiple widgets deep in the tree, avoiding 'prop drilling'. It's a foundational pattern for more advanced state management solutions.
They solve different problems but are both fundamental to Flutter's state management.
Quick Check: State Management
Consider the following scenarios for managing state in a Flutter application. Which statement accurately describes the primary use case for setState versus InheritedWidget?
Recap: setState & InheritedWidget
Congratulations! You've grasped two core concepts of state management in Flutter:
setState: For managing local, internal state changes within aStatefulWidget.InheritedWidget: For efficiently sharing data with widgets deep in the tree, avoiding 'prop drilling'.
These foundational patterns are key to building responsive and maintainable Flutter applications. You're now ready to explore more advanced state management solutions!
자주 묻는 질문
“setState 및 InheritedWidget” 강의는 무료인가요?
네 — “setState 및 InheritedWidget” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Flutter Mobile Development 강의 전체를 잠금 해제할 수 있습니다. Flutter Mobile Development 강의에는 총 4개의 강의가 포함되어 있습니다.
“setState 및 InheritedWidget”에서 뭘 배우나요?
`setState`를 사용한 로컬 상태 관리의 기초를 익히고, 위젯 트리 아래로 데이터를 전달하는 `InheritedWidget`의 개념을 이해합니다. 브라우저에서 직접 실행하는 실습 코드로 Flutter Mobile Development을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Flutter Mobile Development을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Flutter Mobile Development은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.
“setState 및 InheritedWidget” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Flutter Mobile Development 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Flutter Mobile Development 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- setState 및 InheritedWidget
- Provider 패키지 기초
- 상태 관리를 위한 Riverpod
- Stream을 활용한 BLoC 패턴