Flutter 위젯 생명 주기

context·2023년 4월 3일
0

Flutter

목록 보기
5/7

StatelessWidget

statelesswidget은 빌드 시 생성자가 실행된다.
이후, 필수로 override 해야하는 build()가 실행된다. build에서 반환한 위젯이 화면에 렌더링된다.

모든 위젯은 Widget 클래스를 상속하고, Widget 클래스는 불변성을 갖는다.
불변 : 클래스를 한 번 생성하고 나면, 속성을 변경할 수 없다.

위젯의 속성이 변경이 필요할 경우, 예로 생성자에 새로운 매개변수가 있을 경우.
build 시, 변경된 매개변수를 기반으로 build를 재실행해야한다.
하지만, 해당 statelesswidget은 불변으로, 재실행되지 않고, 인스턴스를 아예 새로 생성 후, 기존 인스턴스로 대체해 화면에 반영한다.

StatefulWidget

위를 해결하기 위해, 위젯 내부에서 자체적으로 build()를 재실행.
statefulWidget은 Widget 클래스와 State 클래스로 구성되고, 생명주기가 훨씬 복잡.

위젯의 3가지 생명주기

  • 상태 변경이 없는 생명주기
    위젯이 화면에 나타나며, 생성되고, 화면에서 사라지면, 삭제되는 과정
    1. StatefulWidget Constructor 실행
    2. createState() 실행 - 필수 override 함수로, state를 생성.
    3. state 생성과 함께 initState() 실행
    4. didChangeDependencies() 실행 - BuilderContext가 제공되고, State가 의존하는 값이 변경되면 재실행 (useEffect 느낌인가..)
    5. state의 상태가 dirty로 설정. build()가 재실행되어야 한다.
      이 때, UI가 바뀐 상태로 재생성된다.
    6. state의 상태가 clean로 설정. 화면에 변화가 없으면 state 유지.
    7. 위젯이 위젯 트리에서 사라지면, deactivate(), State가 일시적 또는 영구적으로 삭제될 때 실행.
    8. dispose() 위젯이 삭제될 때 실행.
  • StatefulWidget 생성자의 매개변수가 변경됐을 때
    위젯 생성 후, 삭제 되기 전, 매개변수 변경 시의 과정
    1. 마찬가지로 StatefulWidget 실행 후, State의 didUpdateWidget() 실행
    2. State가 dirty로 변경, build() 실행 후, clean 상태.
  • State 자체적으로 build()를 재실행할 때
    State는 setState()로 build()를 자체적으로 재실행한다.
    1. setState() 실행
    2. dirty -> build() -> clean

Timer

특정 시간 이후, 일회성 또는 지속적으로 함수 실행(SetInterval 느낌..)

Timer.periodic( //SetInterval...(Timer()는 setTimeOut..)
	Duration(seconds: 3), // 주기
    (Timer timer){} // callback
)

StatelessWidget 내 build에 타이머 사용할 경우, 위젯 생성 때마다 Timer 재생성. (즉, build()시 마다 Timer 재생성으로, 메모리 릭 발생)

따라서, StatefulWidget 내 initState()를 통해서, 타이머 한 번만 생성.

class HomeScreen extends StatelessWidget // X
class HomeScreen extends State<HomeScreen> // O

State 내 Timer 반영

import 'dart:async';

class HomeScreen extends State<HomeScreen> {
	final PageController pageController = PageController(); // 컨트롤러 생성
    
	@override
    void initState() {
    	super.initState(); // 부모 initState() 실행(필수)
        
        Timer.periodic(
        	Duration(seconds: 3),
            	(timer){
                	int? next = pageController.toInt();
          //page getter 내에선 page값 double로 들어옴.
                    if(next === null){
                    	return;
                    }
                    if(next === 4){
                    	next = 0;
                    } else {
                    	next++;
                    }
                    pageController.animateToPage(
                    	next,
                        duration: Duration(milliseconds: 500),
                        curve: ~
                    )
                }
        )
    }
    @override
    Widget build(BuildContext context){
    	return Scaffold(
        	body: PageView(
            	controller: pageController // pageController 등록
            )
        )
    }
}

이미지 사이즈

BoxFit.contain : 이미지가 잘리지 않는 선에서 최대 크게 늘림. 부모보다 작을 경우, 여백이 생김.
BoxFit.cover : 부모 위젯을 전체 덮는 선에서, 최소한의 크기로 조절. 여백은 없지만, 가로 또는 세로로 이미지가 잘릴 수 있음.
BoxFit.fill : 이미지 비율 무시하고, 부모 위젯에 이미지 비율을 맞춘다.
BoxFit.fitHeight : 이미지 비율 유지한 채, 높이만 부모 위젯가 맞춘다.
BoxFit.fitWidth : 이미지 비율 유지한 채,
BoxFit.none : 원본 비율 그대로
BoxFit.scaleDown : 원본 비율 그대로, 이미지 중앙 정렬, 부모 위젯이 이미지보다 작으면 이미지 크기를 줄여서 부모 위젯에 맞춤.

시스템 UI 설정

SystemChrome.setEnableSystemUIModel() : 앱의 풀스크린 모드 지정.
배터리, 시간 다 안보이게 함.
setPreferredOrientations() : 앱 실행 방향 지정
setSystemUIChangeCallback() : 시스템 UI 변경 시 콜백 실행
setSystemUIOverlayStyle() : 시스템 UI 색상 변경

setState()

State를 상속하는 모든 클래스는 해당 함수를 사용 가능.

1. StatefulWidget은 렌더링이 끝나고, 항상 Clean의 상태이다. 모든 상태는 Clean 상태에서 변경해야 한다.
2. setState()를 통해 속성을 변경한다.
3. 속성 변경 시 위젯은 Dirty 상태로 변경된다.
4. build( ) 재실행 후, State는 Clean 상태가 된다.

  • setState( )는 매개변수 하나를 입력 받는다.
    이 매개변수는 콜백 함수이며, 콜백 함수에 변경하고 싶은 속성을 입력하면, 코드 반영 뒤 build()를 실행한다. (비동기로 실행되선 안된다.)

0개의 댓글