오늘은 setState 에 대해서 정리했습니다.
개발환경 : 윈도우11, 안드로이드 스튜디오(Arctic Fox 2020.3.1 Patch 4), flutter 2.10
소스코드 위치 - Release setState_Test · mike-bskim/provider_overview (github.com)
setState 를 사용하면 얼마나 많은 부분을 다시 랜더링할까요?
몇단계의 위젯으로 나눠서 아래와 같은 앱을 만들었습니다.
먼저 화면설명은 아래와 같습니다.
앱을 실행하면 처음에 아래와 같이 각 위젯별 build 로그를 출력됩니다.
I/flutter ( 5490): -----------------------------------
I/flutter ( 5490): MyApp >> build
I/flutter ( 5490): ===================================
I/flutter ( 5490): MyHomePage >> build
I/flutter ( 5490): CounterA >> build
I/flutter ( 5490): Middle >> build
I/flutter ( 5490): CounterB >> build
I/flutter ( 5490): Sibling >> build
"increment" 버튼 클릭시 setStage 는 MyHomePage 에서 호출되므로 하위의 모든 위젯들이 다시 랜더링됩니다.
I/flutter ( 5490): ===================================
I/flutter ( 5490): MyHomePage >> build
I/flutter ( 5490): CounterA >> build
I/flutter ( 5490): Middle >> build
I/flutter ( 5490): CounterB >> build
I/flutter ( 5490): Sibling >> build
전체 소스 코드는 "더보기" 클릭하면 볼수 있습니다.
더보기
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
debugPrint('-----------------------------------');
debugPrint('MyApp >> build');
return MaterialApp(
title: 'Counter',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int counter = 0;
void increment() {
setState(() {
counter++;
});
}
@override
Widget build(BuildContext context) {
debugPrint('===================================');
debugPrint('MyHomePage >> build');
return Scaffold(
appBar: AppBar(
title: const Text('My Counter'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
color: Colors.blue[100],
padding: const EdgeInsets.all(20.0),
child: const Text(
'MyHomePage',
style: TextStyle(fontSize: 24.0),
),
),
const SizedBox(height: 20.0),
CounterA(
counter: counter,
increment: increment,
),
const SizedBox(height: 20.0),
Middle(counter: counter),
],
),
),
);
}
}
class CounterA extends StatelessWidget {
final int counter;
final void Function() increment;
const CounterA({
Key? key,
required this.counter,
required this.increment,
}) : super(key: key);
@override
Widget build(BuildContext context) {
debugPrint('CounterA >> build');
return Container(
color: Colors.red[100],
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
Text(
'$counter',
style: const TextStyle(fontSize: 48.0),
),
ElevatedButton(
onPressed: increment,
child: const Text(
'Increment',
style: TextStyle(fontSize: 20.0),
),
),
],
),
);
}
}
class Middle extends StatelessWidget {
final int counter;
const Middle({
Key? key,
required this.counter,
}) : super(key: key);
@override
Widget build(BuildContext context) {
debugPrint('Middle >> build');
return Container(
color: Colors.grey[200],
padding: const EdgeInsets.all(20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
CounterB(counter: counter),
const SizedBox(width: 20.0),
Sibling(),
],
),
);
}
}
class CounterB extends StatelessWidget {
final int counter;
const CounterB({
Key? key,
required this.counter,
}) : super(key: key);
@override
Widget build(BuildContext context) {
debugPrint('CounterB >> build');
return Container(
color: Colors.yellow[100],
padding: const EdgeInsets.all(10.0),
child: Text(
'$counter',
style: const TextStyle(fontSize: 24.0),
),
);
}
}
class Sibling extends StatelessWidget {
const Sibling({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
debugPrint('Sibling >> build');
return Container(
color: Colors.orange[100],
padding: const EdgeInsets.all(10.0),
child: const Text(
'Sibling',
style: TextStyle(fontSize: 24.0),
),
);
}
}
여기서 Sibling() 호출시 const 키워드를 붙이면 랭더링시 다시 build 하지 않습니다. 다른 상태관리 패키지를 사용하지 않고 쉽게 랜더링 비용을 줄일수 있는 방법입니다.
// increment 버튼을 2번 클릭한 로그
I/flutter ( 5490): ===================================
I/flutter ( 5490): MyHomePage >> build
I/flutter ( 5490): CounterA >> build
I/flutter ( 5490): Middle >> build
I/flutter ( 5490): CounterB >> build
I/flutter ( 5490): ===================================
I/flutter ( 5490): MyHomePage >> build
I/flutter ( 5490): CounterA >> build
I/flutter ( 5490): Middle >> build
I/flutter ( 5490): CounterB >> build
[참고자료] udemy - Flutter Provider Essential 코스 (Korean)
'Flutter > 07 State - Provider' 카테고리의 다른 글
[Flutter] Provider Access - Named route (0) | 2022.05.06 |
---|---|
[Flutter] Provider Access - Anonymous route (0) | 2022.05.06 |
[Flutter] Could not find the correct Provider (0) | 2022.05.05 |
[Flutter] Consumer, Selector (0) | 2022.05.05 |
[Flutter] ChangeNotifierProvider (0) | 2022.05.04 |