! 첫 플루터 공부. 역시 처음은 너무 어렵다😂 책은 파이썬 공부했던 것과 마찬가지로 기본템 Do it! 플러터 앱 프로그래밍이다. 파이썬 책과는 다르게 이 책은 자바와 어느 정도 컴퓨터 프로그래밍 언어에 대해 알고 있어야 그나마 학습이 빠를 것 같다. 하지만 난 자바는 1도 모르는 걸... 해봅시다
앱에서 위젯은 특정한 기능을 담당한 부품이라고 볼 수 있다. 앱에서 위젯은 클래스로 구현하고 이를 상속 받는 다양한 위젯이 있다.
예를 들면, Text 클래스는 글자를 전문적으로 표시하는 위젯이고,
Button 클래스는 버튼을 표시하는 위젯이다. 실습 중에 Switch 클래스도 등장하는데,
안드로이드에서는 이를 xml에서 표현하는데 플루터에 경우 코드 단에서 뷰를 구현하는 게 신기했다! (안드로이드 Compose 공부도 얼른 해봐야지)
간단하게 MyApp클래스로 화면을 만들어보는 실습을 해보자
void main(){
runApp(MyApp());
}
class MyApp extends StatelessWidget{
Widget build(BuildContext context) {
return MaterialApp{
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
처음에 설명은 없고 코드만 주루룩 나와서 매우 당황함😯
하지만 다음 장에 설명이 나와 있었다!
클래스 이름 뒤의 extends의 경우는 다트에서 상속을 의미하는 키워드이다.
안드로이드로 쓴다면 class MyApp : StatelessWidget 느낌?
여기서 StatelessWidget이라는 클래스를 상속 받았는데 이 클래스의 경우는 상태가 변경되지 않는 위젯이라고 한다.
@override 에너테이션을 통해 build()라는 함수를 재 정의했다.
이 build() 함수에는 어떠한 위젯을 만들 것인지를 정의한다. 전에 다트 설명에서도 말했듯이 다트의 경우는 main()함수를 활용한다.
그래서 이 runApp()이라는 함수를 이용해 클래스를 실행할 때는 MaterialApp()함수를 반환해야 한다. 여기서 MaterialApp은 그림을 그리는데 필요한 종이라고 생각하면 된다. 여기서 title, theme, home등을 정의하고 그리는 것이다.
메인 색상을 지정하는 primarySwatch 속성이 있고,
visualDensity 속성은 플루터의 특성! 모바일, 웹, 데스크톱, 맥 등 어느 플랫폼에서도 자연스럽게 보이도록 지원한다.
home에는 앱을 실행할 때 첫 화면에 어떤 내용을 표시할지 정한다.
플러터 앱의 위젯은 stateless와 statefull 두 가지로 구분한다.
이 두 가지 구분의 기준은 상태 연결과 관련이 있다.
예를 들어 온보딩과 같은 경우는 화면의 상태가 변화하지 않고 그냥 정적인 상태로 있기 때문에 이 때에는 stateless 위젯을 사용한다.
반면, 계산기와 같이 숫자가 변화하는 뷰를 만들 경우 이는 앱이 위젯의 상태를 보다가 위젯이 특정 상태가 될 때 알맞은 처리를 수행해야 한다. 즉 상태가 연결된 동적인 위젯을 statefull 위젯이라고 하는 것이다.
우리가 위에서 실습했던 위젯의 경우는 상태 변화가 없는 정적인 상태로 있기 때문에 stateless를 사용한 것이다.
Text 클래스 뿐만 아니라 switch라는 위젯도 있는데 이를 한번 사용해 보도록 하겠다. 추가로 머테리얼 디자인도 적용해 볼 예정이다.
void main(){
runApp(MyApp());
}
class MyApp extends StatelessWidget{
var switchValue = false;
Widget build(BuildContext context) {
return MaterialApp(
title: 'Hotaek Flutter',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
darkTheme: ThemeData.light(),
home:Scaffold(
body: Center(
child: Switch(
value: switchValue,
onChanged: (value){
switchValue = value;
}
),
),
)
);
}
}
위에서 배운 StatelessWidget을 상속받은 MyApp 클래스에서 Scaffold를 이용해 스위치를 구성했다.
사용자가 누를시 true, false값이 switchValue값으로 들어가 스위치 상태가 변한다.
하지만 우리는 StatelessWidget 클래스를 상속받았기 때문에 위젯의 상태 변경에 따른 값을 화면에 반영하지 못하므로 스위치기 움직이는 변화를 볼 수가 없다. 그럼 어떻게 하냐??
StatefulWidget과 setState()함수를 활용해보자!!
class MyApp extends StatefulWidget {
State<StatefulWidget> createState() {
return _MyApp();
}
}
class _MyApp extends State<MyApp>{
var switchValue = false;
Widget build(BuildContext context) {
return MaterialApp(
title: 'Hotaek Flutter',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
darkTheme: ThemeData.light(),
home:Scaffold(
body: Center(
child: Switch(
value: switchValue,
onChanged: (value){
setState((){
switchValue = value;
});
}
),
),
)
);
}
}
_MyAPP이라는 클래스를 만들었다!!
StatefulWidget의 경우 혼자서 화면 출력을 할 수 없고 State라는 클래스가 필요하다. 그래서 State클래스 상속받는 _MyApp 클래스를 만들고 안에 우리가 위에서 만들어 놓은 위젯을 담는다.
그리고 StatefulWidget 클래스를 상속받는 MyApp에 createState() 함수를 재정의하고 _MyApp클래스를 호출한다! 이럴 경우 MyApp클래스가 현재 화면을 주시하고 상태가 변경되면 이를 감지하고 _MyApp클래스가 화면을 갱신한다.
추가로 화면 갱신을 위해 setState()라는 함수를 사용했다
!
스테이트리스 위젯의 경우는 갱신할 수 없기 때문에 생명주기가 없다. 그러므로 화면이 넘어갈 경우 모든 로직이 종료된다.
반면 스테이풀 위젯은 10단계로 구분하는 생명주기가 있다!!
먼저 StatefulWidget 클래스를 상속받는 클래스는 반드시 createState() 함수를 호출해야 한다.
이 함수의 경우는 다른 생명주기 함수들이 포함된 State 클래스를 반환한다. == 위젯의 상태를 생성하는 함수 이다.
class MyHomePage extends StatefulWidget {
_MyHomePageState createState() => new _MyHomePageState();
}
createState() 함수가 호출되어 상태가 생성되면 바로 mounted 속성이 true로 변경된다.
여기서 mounted 속성이 true라는 것은 위젯을 제어할 수 있는 buildContext 클래스에 접근할 수 있다는 의미이다.
buildContext가 활성화 되어야만 우리가 Switch 위젯을 만들때 사용했었던 setState() 함수를 이용할 수 있다.
위 함수는 위젯을 초기화할 때 한 번만 호출한다. 그래서 주로 데이터 목록을 만들거나 처음 필요한 데이터를 주고받을 때 호출한다.
initState(){
super.initState();
_getJsonData();
}
위의 코드는 서버에서 받아온 데이터를 화면에 출력할 수 있도록 한다.
이 함수는 데이터에 의존하는 위젯이라면 화면에 표시하기 전에 꼭 호출해야한다! 주로 상속받은 위젯을 사용할 때 상속받는자가 변경되면 호출한다.
이 함수는 Widget을 반환한다. 즉 위젯을 화면에 띄우는 함수이다. 우리가 위에 앱을 만들 때도 재정의했던 함수이다.
부모 위젯이나 데이터가 변경되어 위젯을 갱신해야 할 때 호출한다. 만약 initState()에서 특정 이벤트에 의해 위젯이 변경되면 didUpdateWidget()함수를 호출해 위젯을 갱신할 수 있다.
데이터가 변경되었다는 것을 알려주고 변경된 데이터를 이용해 화면의 UI를 변경할 수 있도록 한다. 가장 많이 사용됨!!
State 객체가 플러터의 구성 트리로부터 제거될 때 호출된다. 하지만 해당 메모리까지는 지워지지 않아서 dispose() 함수를 호출하기 전까지 State 객체를 재사용할 수 있다.
deactivate()에 이어 State 객체를 영구적으로 소멸할 때 호출한다. 즉 이 함수를 사용하면 해당 위젯을 종료한다는 뜻이다
State 객체가 소멸하면 마지막으로 mounted 속성이 false로 되면서 생명주기가 끝난다.