android | 안드로이드 프로젝트 관련 파일 | 안드로이드 스튜디오로 실행 가능 |
---|---|---|
ios | iOS 프로젝트 관련 파일 | 맥 전용 엑스코드로 실행 가능 |
lib | 플러터 앱 개발을 위한 다트 파일 | 플러터 SDK 설치 필요 |
test | 플러터 앱 개발 중 테스트 파일 | 테스트 편의성 제공 |
pubspec.yaml
. pubspec.yml 파일은 플러터에서 다양한 패키지와 이미지, 폰트 등을 사용하게 해 줌.main.dart
로 lib 폴더 안에 있음.import 'package:flutter/material.dart';
이 패키지에는 플러터의 UI와 관련된 모든 클래스가 있어 자주 사용함extends
(상속을 나타내는 키워드)를 써서 클래스로부터 상속 가능@override
에너테이션을 사용해 함수 재정의도 가능함.플러터 앱을 구성하는 위젯은 스테이트리스와 스테이트 풀 두 가지로 구분 가능함.
이 구분은 상태 연결과 관련이 있음
StatelessWidget
클래스를 상속받아 만듦.Stateful Widget
클래스를 상속받아 만듦. 스테이트 풀 위젯은 언제든 상태가 변경되면 특정한 처리를 수행해야 하므로 항상 지켜봐야 함. 메모리나 CPU 등 자원을 그 만큼 많이 사용함. (+) 스테이트 풀 위젯은 혼자서 화면을 출력할 수 없고 State 클래스가 필요함. 그러므로 State 클래스를 상속 받는 내부 클래스를 만들고 그 안에 앞에서 만들어 놓은 위젯을 담아야 함. 그 상속 받은 클래스는 createState() 함수를 재정의한 후 함수를 호출함. 그렇게 하면 해당 클래스가 현재 화면을 보다가 상태가 변경되면 이를 감지하고 내부 클래스가 화면을 갱신함. ⇒ createState
로 상태를 만들고, setState
로 변경한 스테이트를 적용하는 형식..
.
.
onPressed: (){
if (_color == Colors.blue){
setState(() {
test = 'flutter';
_color = colors.amber;
}}
}
.
.
.
home: Center(
child : Text('Hello', textAlignL TextAlign.center)
));
.
.
.
home: Container(
child : Center(
child : Text('Hi')
)
)
스테이트리스 위젯은 한 번 만들어지면 갱신할 수 없으므로 생명주기가 없음.
즉, 다른 위젯으로 넘어가면 모든 로직이 종료됨.
그러나 스테이트풀 위젯은 10단계로 구분하는 생명주기가 있음.
[추가] 왜 State와 StatefulWidget 클래스를 나눠 놓아 고통받게 만들었을까?
상태를 생성하는 createState() 함수
먼저 statefulWidget을 상속받는 클래스는 반드시 createState() 함수를 호출해야 함.
이 함수는 다른 생명주기 함수들이 포함된 State 클래스를 반환함. 즉, 위젯의 상태를 생성하는 함수임.
위젯을 화면에 장착하면 mounted == true
createState() 함수가 호출되어 상태가 생성되면 곧바로 mounted 속성이 true로 변경됨.
mounted 속성이 true라는 것은 위젯을 제어할 수 있는 buildContext 클래스에 접근할 수 있다는 의미와 동일함.
buildContext가 활성화되어야 비로소 setState() 함수를 이용할 수 있음. 아니면 오류가 발생함.
화면 구성도 안 되었는데 setState() 함수로 위젯을 건드릴 수는 없음.
다음처럼 setState() 함수를 호출하기 전에 mounted 속성을 점검 코드로 사용하면 좀 더 안전하게 코드를 작성할 수 있음.
if (mounted){
setState()
}
위젯을 초기화하는 initState() 함수
initState() 함수는 위젯을 초기화할 때 한 번만 호출함.
데이터 목록을 만들거나 처음 필요한 데이터를 주고 받을 때 사용함.
initState() 함수를 호출할 때 내부에서 _getJsonData() 함수를 호출해 서버에서 받아온 데이터를 화면에 출력하게 만들 수 있음.
만약 네트워크 통신이 안 되거나 데이터가 이상하다면 화면에 표시하기 전에 미리 알아서 적절하게 대응해야 하므로 위젯을 초기화하는
initState() 함수에서 데이터를 준비해놓는 것이 좋음.
의존성이 변경되면 호출되는 didChangeDependencies() 함수
initState() 함수가 호출된 후에 이어서 바로 호출되는 함수가 didChangeDependencies()
이 함수는 데이터에 의존하는 위젯이라면 화면에 표시되기 전에 꼭 호출해야 함.
주로 상속받은 위젯을 사용할 떄 피상속자가 변경되면 호출함.
화면에 표시하는 build() 함수
해당 함수는 위젯을 반환함. ( = 화면에 위젯을 렌더링함)
build 함수에서 위젯을 만들고 반환하면 비로소 화면에 표시됨.
위젯을 갱신하는 didUpdateWidget() 함수
부모 위젯이나 데이터가 변경되어 위젯을 갱신해야 할 때 호출함. 만약 initState()에서 특정 이벤트에 의해 위젯이 변경되면
didUpdateWidget() 함수를 호출해 위젯을 갱신할 수 있음.
initState() 함수는 위젯을 초기화할 때 한 번만 호출되므로 위젯이 변경되었을 때 호출하는 didUpdateWidget() 같은 함수가 필요함.
위젯의 상태를 갱신하는 setState() 함수
setState() 함수를 이용하면 데이터가 변경되었다는 것을 알려주고 변경된 데이터를 이용해 화면의 UI를 변경할 수 있도록 함.
플러터 앱을 만든다는 것은 곧 앱의 화면을 구성하는 일이므로 제일 많이 호출하는 함수.
위젯의 상태 관리를 중지하는 deactiviate() 함수
deactiviate() 함수는 State 객체가 플러터의 구성 트리로부터 제거될 때 호출됨.
다만, State 객체가 제거되었다고 해서 해당 메모리까지 지워지지는 않음.
dispose() 함수를 호출하기 전까지는 State 객체를 재 사용 가능함.
위젯의 상태 관리를 완전히 끝내는 dispose() 함수
state 객체를 영구적으로 소멸할 때 호출.
네트워크 통신이나 스트림 통신을 하다가 dispose() 함수를 호출하면 데이터 전송을 중지함.
그리고 위젯을 소멸할 때 꼭 호출해야 하는 함수라면 dispose() 함수 내에서 호출해야 함.
앞에서 살펴 본 dispose() 함수 호출로 State 객체를 트리에서 제거한 후에 같은
State를 다시 다른 트리에 재사용할 경우 dispose() 함수가 호출되지 않을 수 있음. (물론 흔한 경우는 아님!)
위젯을 화면에서 제거하면 mounted == False
State 객체가 소멸하면 마지막으로 mounted 속성이 false로 되면서 생명주기가 끝남.
mounted 속성이 false라는 의미는 이 state는 재사용할 수 없다는 의미와 동일함.
그러므로 setState() 함수를 호출하면 오류가 발생함.