12. 플러터 : 버튼 (Stateless vs. Stateful)

사용자가 액션을 취하고
그 액션에 대응해서 뭔가를 한다는 것은 역시 피곤하다.

이전 글에서 하려던..
버튼을 눌렀을 때 다른 색상으로 버튼 배경색을 변경해 보자.
버튼을 누를 때마다 검정색과 파랑색이 번갈아 나타나도록 처리했다.



계속해서 사용하던 MyApp 클래스 대신 MyButton 클래스를 만들었고
StatelessWidget 클래스 대신 StatefulWidget 클래스를 상속 받고 있다.
StatelessWidget 클래스는 build 함수에서 생성한 객체를 반환했지만
StatefulWidget 클래스는 createState 함수에서 생성한 객체를 반환하는 부분이 일단 가장 달라 보인다.

import 'package:flutter/material.dart';

void main() {
runApp(MaterialApp(
title: '버튼',
home: Scaffold(
appBar: AppBar(title: Text('버튼'),),
body: MyButton(),
),
));
}

class MyButton extends StatefulWidget {
@override
State createState() {
return MyButtonState();
}
}

class MyButtonState extends State<MyButton> {
var backColor = Colors.black;

@override
Widget build(BuildContext context) {
return Center(
child: RaisedButton(
child: Text('상태'),
onPressed: () {
// 에러는 아니지만, 배경색을 바꿀 수 없음
// backColor = Colors.lightBlue;

setState(() {
backColor = (backColor == Colors.black) ? Colors.lightBlue : Colors.black;
});
},
textColor: Colors.white,
color: backColor,
),
);
}
}


이전 글에서 color 속성이 final로 정의됐기 때문에 직접 변경할 수 없다는 것은 알았다.
플러터에서 제공하는 방법은 상태(state)를 통한 위젯 재구축(re-build)이다.
RaisedButton 클래스는 상태를 갖지 않는 StatelessWidget 클래스를 상속 받기 때문에
생성자를 통해서 필요한 값들을 전달하고 나면 메모리에서 삭제될 때까지 그 상태를 유지해야 한다.
새로운 상태를 주고 싶다면 없애고 다시 만드는 방법밖에 없다.

그런데 이전 글에서는 버튼 생성을 build 함수에서 하고 있기 때문에
결국 버튼을 다시 만드는 방법은 build 함수를 호출하는 것밖에 없는데.. 이게 어렵다.
그래서 우리 대신 build 함수를 대신 호출해 줄 수 있는 StatefulWidget 클래스를 사용해서 처리한다.
다시 말하지만 StatelessWidget 클래스의 build 함수는 최초 생성할 때 1회 호출되고 다시 호출할 수 없다.
다시 호출한다는 것은 새로운 객체를 만든다는 뜻이다.

StatefulWidget 클래스의 build 함수를 세터(setter)를 통해 자동 호출되도록 설계되었다.
세터를 정의하는 방법은 코드에서 보는 것처럼
onPressed 매개변수에 전달할 함수에서 setState 함수를 호출하면 된다.
그런데 setState 함수가 필요로 하는 매개변수가 함수이기 때문에 다시 함수를 정의한다.
이때 사용하는 함수는 매개변수도 없고 반환값도 없다.

setState 함수는 두 가지 역할을 하게 된다.
함수 호출을 했으니까 해당 함수가 해야할 세터로써의 역할과
매개변수로 전달된 함수를 호출하는 역할.
매개변수로 넘어온 함수를 호출해서 멤버변수의 값을 바꾸고
바뀐 값이 반영되도록 build 함수를 호출하는 것이 setState 함수가 하는 역할이다.

참.. StatefulWidget은 State 클래스와 연동해서 사용하도록 설계되었다.
크기가 작은 경우에는 기능을 하나로 합치는 것이 좋지만
프로젝트 규모가 커질 때를 생각하면 나뉘어 있는 것이 좋다.
객체의 상태를 유지하는 MyButtonState 클래스와
객체를 관리하는 MyButton 클래스가 그것이다.
문제는 해당 코드를 어떤 클래스에 넣는지가 어려운 데
이후 코드를 통해 정리해 나가도록 하자.

문제 하나 낸다.
버튼이 눌릴 때마다 "검정색"과 "파랑색" 글자로 버튼 제목을 변경해 보자.
기존 코드에 조금만 살을 붙여본다.

'플러터' 카테고리의 다른 글

14. 플러터 : 버튼 + 사진  (0) 2019.02.07
13. 플러터 : 버튼 확장  (0) 2019.02.07
12. 플러터 : 버튼 (Stateless vs. Stateful)  (0) 2019.02.07
11. 플러터 : 버튼  (0) 2019.02.07
10. 플러터 : 사진 옵션(BoxFit)  (0) 2019.02.03
9. 플러터 : 사진 배치  (0) 2019.02.03