[flutter9] Widget Life Cycle

한별onestar·2024년 5월 21일

flutter 실전

목록 보기
10/15
post-thumbnail

Widget Life Cycle

Widget Life Cycle❓

위젯이 화면에 나타나는 순간부터 화면에서 사라지는 순간까지 일어나는 일을 정의해 놓은 것


️✔️ StatelessWidget Life Cycle

StatelessWidget일 경우에는 생성자가 처음 실행이 되고 그 다음에 빌드 함수를 실행한다. 이 걸 증명하기 위해서 코드를 작성해 보았다 프로젝트 초기화 후에 코드를 작성했다.

import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {

  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: HanByeulWideget(),
    );
}
}

class HanByeulWideget extends StatelessWidget {
  HanByeulWideget({super.key}){
    print('-----생성자-----');
  }

  @override
  Widget build(BuildContext context) {
    print('-----빌드-----');
    return Container(
      width: 50,
      height: 50,
      color: Colors.red,
    );
  }
}
  • 결과 (console)
Performing hot restart...
Syncing files to device iPhone 15 Pro Max...
Restarted application in 262ms.
flutter: -----생성자-----
flutter: -----빌드-----
flutter: -----생성자-----
flutter: -----빌드-----

콘솔창을 확인해 보면 생성자가 먼저 실행되고 빌드 함수가 실행된다.

❗️맨 처음 실행했을 때에는 모든 위젯이 두 번 생성된다.



️✔️ StatefulWidget Life Cycle1

일단 StatefulWidget인 HanByeulWidget을 HomeScreen에 정의했다.

import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {

  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: HanByeulWidget(),
    );
}
}
/*StatefulWidget*/
class HanByeulWidget extends StatefulWidget {
  @override
  State<HanByeulWidget> createState() => _HanByeulWidgetState();
}
/*State 클래스*/
class _HanByeulWidgetState extends State<HanByeulWidget> {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 50,
      height: 50,
      color: Colors.orange,
    );
  }
}

그리고 빌드가 되는 순서는 그냥 냅다 적어보기로 하자 왜냐면 먼 말인지 1도 모르겠기 때문이다.

HanByeulWidget

Constructor() ➡️ createState()

가장 먼저 실행되는 건 생성자이고 StatefulWidget은 무조건 creatState()함수를 정의해 주어야 한다. 이 createState()함수는 _HanByeulWidgetState 이라는 State클래스를 생성한다.

_HanByeulWidgetState

initState() ➡️ didChangeDependencies() ➡️ dirty ➡️ build() ➡️ clean ➡️ deactivate() ➡️ dispose()

❗️위젯이 생성되는 이 라이프사이클 중에서 어떤 상황에 우리가 특정 함수나 기능을 실행하고 싶을 때 실행하고 변경할 수 있도록 특정 라이프 사이클 구간에 함수를 정의해 제공한 것
  • initState()
    State클래스에서는 constructor이야기를 하지 않고 initState()가 중요하다. State클래스가 인스턴스화 됐을 때 딱 한 번 실행되는 함수이다.

  • didChangeDependencies()
    init() 함수에서 context를 사용하지 못하는데 didChangeDependencies() 함수에서 context를 제공한다. 그리고 여러 번 실행될 수 있다. State클래스가 의존성이 변경됐을 때 다시 실행이 된다는데 대체 먼말이냐 진짜로 하
    예를 들어 Theme.of(), MediaQuery.of()같은 기능을 사용할 때 이 함수를 다시 실행할 수 있다는 것. 짜증난다 어려워서.

  • Dirty, Clean
    클래스의 상태를 말한다. 빌드가 실행돼야 하는 상태는 Dirty, 빌드가 실행된 다음의 상태 Clean

  • deactivate(), dispose()
    state가 삭제되고 화면에서 사라지면 deactivate(), dispose()함수가 차례로 실행된다. 위젯이 화면에서 지워졌을 때 실행된다.



️✔️ StatefulWidget Life Cycle2 _ setState

SetState실행했을 때 Life Cycle

import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {

  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: HanByeulWidget(),
    );
}
}

class HanByeulWidget extends StatefulWidget {
  const HanByeulWidget({super.key});

  @override
  State<HanByeulWidget> createState() => _HanByeulWidgetState();
}

class _HanByeulWidgetState extends State<HanByeulWidget> {
  Color color = Colors.blue;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: (){
        setState(() {
          color = color == Colors.red ? Colors.blue : Colors.red;
        });
      },
      child: Container(
        width: 50,
        height: 50,
        color: color,
      ),
    );
  }
}

컨테이너를 누를 때 onTap() 함수가 실행된다. 라이프사이클을 살펴보자.

HanByeulWidget

Constructor() ➡️ createState()

요건 똑같

_HanByeulWidgetState

initState() ➡️ didChangeDependencies() ➡️ dirty ➡️ build() ➡️ clean
까지 처음 화면이 생성 되었을 때 실행된 후 컨테이너를 누를 때 마다 setState가 실행되도록 설계를 한 것 setState는 빌드 함수를 다시 실행시켜 state 클래스를 다시 dirty상태로 만든다. 그리고 빌드가 다시 실행되고 clean상태로 만들어 준다.
setState() ➡️ dirty ➡️ build() ➡️ clean

➕ setState함수를 정의하고 안에 컬러를 바꾸는 변수의 변경은 dirty상태가 되기 직전에 일어나게 된다.



️✔️ StatefulWidget Life Cycle 실습 세팅

버튼을 누르면 나타나고 사라지는 박스를 구현해 보자. 여기에 작성된 코드는 모두 프로젝트 초기화 구조를 참고한다. 아래 코드는 home_screen.dart 파일 내부에 작성한다.

import 'package:flutter/material.dart';

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  bool show = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: HanByeulWidget(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 50,
      height: 50,
      color: Colors.blue,
    );
  }
}

일단 화면에 박스를 하나 그렸다. 다음으론 박스를 가운데 정렬하고 버튼을 추가해 본다.

.
.
.
class _HomeScreenState extends State<HomeScreen> {
  bool show = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SizedBox(
        width: double.infinity,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            if (show) HanByeulWidget(),
            SizedBox(height: 32),
            ElevatedButton(
              onPressed: (){},
              child: child,
            ),
          ],
        ),
      ),
    );
  }
}

우선 가운데 정렬은 SizedBox()Column()의 속성으로 레이아웃을 잡았다. 그래고 클래스 내부에 bool show = false라는 변수를 추가했다.

❗️리스트 안의 조건문

children: [
            if (show) HanByeulWidget(),
            .
            .
            .
          ],

리스트 안에서 조건문을 적용시킬 수 있다. 조건문 바로 뒤에 위젯을 작성해 준다. 이건 바로 뒤 위젯에만 해당되고 리스트 안에서만 작성할 수 있는 문법이다. 값이 false이면 위젯은 사라지고 true이면 위젯은 보이게 된다.

❗️SizedBox() 활용

SizedBox(height: 32),

중간에 SizedBox() 위젯을 이용해 여백을 만들어 줄 수 있다.

❗️ElevatedButton() 위젯

ElevatedButton(onPressed: onPressed, child: child)

클릭하면 누른 부분에서 색상이 퍼져나가는 버튼이다. 이 버튼을 활용해 보자.

ElevatedButton(
              onPressed: (){
                setState(() {
                  show = !show;
                });
              },
              child: Text('Click!'),
            ),
  • onPressd() {}
    onPressed 안에는 함수를 넣어준다.
  • setState()
    setState()를 넣어주지 않으면 버튼을 누르고 dirty상태가 되지 않기 때문에 버튼 동작이 안하게 된다. setState()안에 show =!show;를 넣어주어야 코드 가독성이 높아진다.

여기서 가장 중요한 점은 setState()를 넣어주어 dirty상태를 만들어 코드를 작동하게 하는 것 ! 이제 StatefullWidget의 라이프 사이클을 상세하게 알아보자! 총 3가지가 있는데 위에 2가지밖에 간단하게 정리하지 않아서 세세하게 다시 정리를 해보려고 한다.

profile
한별잉

0개의 댓글