Flutter에서 위젯의 생명 주기는 중요한 개념입니다. 특히, StatelessWidget과 StatefulWidget은 동작 방식이 다르기 때문에 각각의 생명 주기를 이해하는 것이 중요합니다.
State 생명 주기
- StatelessWidget과 StatefulWidget은 빌드될 때마다 새로 생성됩니다.
- StatelessWidget은 build 메서드가 호출되면서 한 번만 생성되고 끝납니다.
- StatefulWidget은 내부적으로 State 객체를 생성하며, 생성된 State 객체는 메모리에 유지되면서 생명 주기를 가집니다.
- 한 번 생성된 State는 재사용되며, 필요할 때만 build 메서드가 다시 호출되어 업데이트됩니다.
StatefulWidget의 생명 주기
- StatefulWidget의 생명 주기는 다음과 같은 주요 메서드로 동작함
- createState() : StatefulWidget에서는 createState() 메서드를 통해 State 객체를 생성해야 하며, 전체 생명 주기 중, 한 번만 호출됨
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
- initState() : State 객체가 생성된 후 호출되며, 위젯 상태를 초기화하는 데 보통 사용됨. 전체 생명 주기 중, 한 번만 호출됨
- build() : initState() 호출 후, 호출되며, 개발자가 setState()를 호출하면, build() 메서드가 재호출됨.
- 호출 시마다, 변경된 상태를 기반으로 변경된 UI를 표현
- dispose() : 위젯 트리에서 제거될 때 호출되며, State 객체가 영구적으로 제거되고, 사용 자원이 해제됨
애니매이션 코드 사용해보기
import 'dart:math';
import 'package:flutter/material.dart';
void main() {
runApp(MyWidget());
}
class MyWidget extends StatefulWidget {
const MyWidget({super.key});
@override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget>
with SingleTickerProviderStateMixin {
int _counter = 0; // 1. 버튼이 눌린 횟수를 저장하는 변수입니다.
Color _backgroundColor = Colors.white; // 2. 배경색을 저장하는 변수입니다.
late AnimationController _controller; // 3. 애니메이션의 진행을 제어하는 컨트롤러입니다.
late Animation<double> _animation; // 4. 애니메이션의 스케일 값을 저장하는 변수입니다.
@override
void initState() {
super.initState();
print('메모리에 올라갈 때 한번만 호출이 된다'); // initState는 위젯이 처음 생성될 때 한 번 호출됩니다.
_controller = AnimationController(
// 빌드 할 때 미리 객체를 생성해 두는 녀석 --> 불변 객체가 됨
duration: const Duration(milliseconds: 300), // 5. 애니메이션의 지속 시간을 설정합니다.
vsync: this); // 6. vsync는 화면 새로고침 주기에 동기화하여 애니메이션 성능을 최적화합니다.
// 애니메이션 범위 지정
// Tween을 사용하여 애니메이션 범위 정의 (0.8 ~ 1.0)
_animation = Tween<double>(begin: 0.5, end: 1.0).animate(CurvedAnimation(
parent: _controller,
curve: Curves.easeInOut)) // 7. 애니메이션이 부드럽게 시작하고 끝나도록 설정합니다.
..addListener(() {
setState(() {}); // 8. 애니메이션이 진행될 때마다 화면을 업데이트합니다.
});
}
@override
void dispose() {
_controller.dispose(); // 9. 메모리 누수를 방지하기 위해 애니메이션 컨트롤러를 해제합니다.
super.dispose();
}
// 버튼을 눌렀을 때 호출되는 함수
void _incrementCounter() {
setState(() {
_counter++; // 10. 버튼이 눌릴 때마다 카운터를 증가시킵니다.
_backgroundColor = _getRandomColor(); // 11. 배경색을 랜덤으로 변경합니다.
});
// 11. 애니메이션을 앞으로 진행한 후, 완료되면 원래 상태로 되돌립니다.
_controller.forward().then((_){
_controller.reverse();
});
}
// 랜덤 색상을 생성하는 메서드를 만들자
Color _getRandomColor() {
final random = Random();
return Color.fromARGB(
255,
random.nextInt(256), // R (0~255) 랜덤 값
random.nextInt(256), // G (0~255) 랜덤 값
random.nextInt(256)); // B (0~255) 랜덤 값
}
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
useMaterial3: true, // 12. Material 3 스타일을 적용합니다.
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue)
), // 13. Material 3 컬러 테마의 기본 색상을 지정합니다.
home: Scaffold(
appBar: AppBar(title: Text('애니메시연 및 생명주기'),),
backgroundColor: _backgroundColor, // 14. 배경색을 설정합니다.
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('버튼을 누른 횟수 : ${_counter}', // 15. 버튼이 눌린 횟수를 텍스트로 표시합니다.
style: TextStyle(fontSize: 20),),
SizedBox(height: 20),
// 17. Transform.scale 위젯으로 버튼의 크기를 애니메이션 효과로 조절합니다.
Transform.scale(
scale: _animation.value, // 16. 애니메이션 스케일 값을 적용합니다.
child: ElevatedButton(
style: ElevatedButton.styleFrom(
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12),
),
child: Text('눌러 보기', style: TextStyle(fontSize: 18),) ,
onPressed: _incrementCounter, // 17. 버튼을 누르면 _incrementCounter 함수 호출
),
)
],
),
),
),
);
}
}
코드 설명
- AnimationController 초기화: _controller는 애니메이션의 타이밍을 제어하는 객체로, duration을 통해 애니메이션 속도를 조절하고, vsync는 SingleTickerProviderStateMixin을 통해 화면 새로고침 주기에 동기화하여 성능을 최적화합니다.
- Tween 객체 설정: Tween<double>(begin: 0.8, end: 1.0)은 애니메이션이 시작될 때는 0.8배의 크기에서 시작해, 1.0배 크기로 변하는 애니메이션 효과를 제공합니다.
- Transform.scale 위젯: scale 속성에 애니메이션 값을 적용해 버튼의 크기가 점점 커졌다가 다시 원래대로 돌아오도록 설정합니다.
Flutter에서 애니메이션을 효율적으로 관리하기 위해 vsync와 SingleTickerProviderStateMixin을 사용합니다
1. vsync: this의 역할
- vsync는 "Vertical Synchronization"의 약자로, 애니메이션이 화면의 새로고침 주기와 동기화되도록 도와줍니다.
- 목적: 애니메이션이 화면에 보이지 않거나 필요하지 않은 경우, 불필요하게 자원을 사용하지 않도록 애니메이션을 자동으로 멈춰줍니다.
- 효과: 화면 주기와 맞춰 애니메이션이 실행되므로 CPU와 GPU의 자원 사용을 줄여 효율적으로 동작합니다.
2. SingleTickerProviderStateMixin의 역할
- Ticker는 Flutter에서 애니메이션을 위한 핵심 요소로, 화면을 여러 번 새로 그려 애니메이션을 부드럽게 보여줍니다.
- SingleTickerProviderStateMixin은 Ticker를 한 번만 제공하여, 애니메이션이 필요할 때만 활성화하고 그렇지 않을 때는 비활성화합니다.
- 장점: 애니메이션이 없는 상황에서 Ticker가 불필요하게 작동하는 것을 방지해, 메모리와 자원을 절약합니다.
왜 SingleTickerProviderStateMixin을 써야 할까요?
애니메이션은 Ticker의 도움으로 화면을 반복해서 새로 그리며 동작합니다. 하지만 필요하지 않은 상황에서도 Ticker가 작동하면 자원을 낭비하게 되죠. SingleTickerProviderStateMixin을 사용하면 필요할 때만 Ticker가 작동하도록 관리할 수 있어, 애니메이션을 효율적으로 실행할 수 있습니다.
'Flutter' 카테고리의 다른 글
[Flutter] Flutter에서 Key의 역할과 필요성 (0) | 2024.11.14 |
---|---|
[Flutter] Flutter의 위젯과 Element 트리 그리고 Key의 역할과 사용 방법 (1) | 2024.11.14 |
[Flutter] GestureDetector 위젯 (0) | 2024.11.14 |
[Flutter] 개발자 모드 (0) | 2024.11.14 |
[Flutter] Provider 라이브러리를 사용해보기 (코드 발전 시키기 2) (0) | 2024.11.13 |