Flutter StateFull Widget(feat.dynamic var)

강정우·2023년 5월 9일
0

Flutter&Dart

목록 보기
14/87
post-thumbnail

StateFull Widget

  • 앞서 포스팅한 custome widget을 만드는 방법은 많진 않지만 우리는 Stateless한 Widget을 만들었다.

  • 이는 내부적으로 바뀌는 값이 있다면 매우 잘 못 된 선택이다.
    어떠한 값을 받아서 어떠한 값을 return하는 경우에는 더더욱이 말이다

  • StateFull Widget 닉값을 한다. 즉, 내부적으로 state를 갖는다. 이는 변하며 또 UI에 영향을 미친다.

class DiceRoller extends StatefulWidget {
  const DiceRoller({super.key});
  
  State<DiceRoller> createState() {
    return _DiceRollerState();
  }
}

const 생성자함수

  • StatefullWidget은 non-final하지만 그럼에도 불구하고 생성자함수는 const라고 지정할 수 있다.

  • 왜냐하면 2번째 클래스를 갖고있기 때문이다.

메서드

  • StateFull Widget은 Stateless Widget과 다르게 클래스를 생성할 때 build()를 사용하지 않는다.

  • 대신 createState()를 쓴다. 이 함수는 항상 State type을 return하고 이는 Flutter 에서 제공하는 타입이다.

  • 그리고 State이긴 한데 어떤 State냐 바로 본인 State를 뜻한다.

return

  • return값은 항상 메서드에 사용되는 type를 리턴해야한다.

  • 그리고 그 값은 또 다른 class에서 생성된다.

  • 즉, StatefullWidget를 생성한다면 항상 2개의 클래스를 다뤄야한다.

  • 그래서 2번째 클래스의 이름은 통상 _ 접두어가 붙고 가운데 1번째 클래스 이름이 붙고 접미어로 State가 붙는다.

2번째 클래스 (state class)

class _DiceRollerState extends State<DiceRoller> {
  var activeDiceImage = 'assets/images/dice-2.png';

  void rollDice() {
    activeDiceImage = 'assets/images/dice-4.png';
  }

  
  Widget build(context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        Image.asset(
          activeDiceImage,
          width: 200,
        ),
        ElevatedButton(
          onPressed: rollDice,
          style: TextButton.styleFrom(
            padding: const EdgeInsets.only(
              top: 10,
            ),
            foregroundColor: Colors.white,
            textStyle: const TextStyle(fontSize: 28),
          ),
          child: const Text('주사위 굴리귀!'),
        ),
      ],
    );
  }
}
  • 이렇게 2개로 관리하는 이유는 플러터를 통해 내부에서 특별한 방식으로 관리되기 때문이다.

second class naming

  • 앞서 _ 접두어가 붙는다 했는데 이 _의 의미는 바로 "비공개"라는 것이다.

  • 이렇게 _ 접두어를 붙여놓으면 다른 곳에서 import를 하더라도 해당 클래스에 접근할 수 없다.

second class type

  • 물론 이 2번째 클래스도 무언가를 상속받아야하는데 바로 State<1번째클래스> 이다.

메서드

  • 그리고 여기에 build() 메서드를 추가하면 된다.

생성자 함수

  • 여기서는 const한 생성자함수를 추가하지 않는다. 1. 원래 생성자함수는 기본적으로 생성된다. 2. State obj는 바뀔 수 있기 때문에 const 키워드를 사용하지 않는다.

setState()

  • 물론 Statefull한 widget을 만들고 해당 state를 관리하고 return하기 위해 2번째 클래스도 만들었지만 이는 충분하지 않다.

  • 왜냐하면 플러터는 기본적(default)으로 이를 무시한다.
    무슨 말이야 state가 변경되었다고 build 메서드를 재실행하고 ui를 재평가(업데이트)하지 않는다는 것이다.

  • 바로 setState라는 함수로 update를 해주면 된다.

  • setState는 StatefullWidet를 만들 때 => _어쩌구State 라는 2차 익명class를 만든다 하였고 이때 2차 class는 State를 상속받는다고 하였다.
    바로 이 State 객체에서 받아온 함수가 바로 setState()이다.

  • 즉, State를 상속받아야 setState()를 쓸 수 있따.

  • setState는 무조건 함수를 인수로 갖는다.

  • 그리고 실행문 안에서 비로소 obj 변수, 객체 변수를 최신화할 수 있다.

  • 그리고 해당 build 함수가 실행되면 비로소 플러터는 전과 다른 UI를 찾아 업데이트를 할지 말지 결정한다.

  • 즉, setState가 실행되면 build가 다시 실행고 이때 플러터가 전과 다른 UI들을 찾아 바꿔야할 곳을 전부 바꾼다.

_

  • _ 키워드는 다른 곳에서 쓰지 않겠다. 즉, private하게 쓰겠다는 뜻이다.
    이는 Class 뿐만 아니라 state 클래스 내부에 있는 변수와 메서들에게도 적용가능한 부분이다.

  • 따라서 Class가 priavte(_) 키워드가 없다면 밑에 속성, 메서들에도 없어야 한다. 왜? => Class에 접근은 가능한데 그 하위에 있는 요소들을 전혀사용할 수 없게되기 때문이다.

$

void rollDice() {
  var diceRoll = Random().nextInt(6)+1;
  setState(() {
  	activeDiceImage = 'assets/images/dice-$diceRoll.png';
    });
}
  • JS 처럼 $ 키워드는 쓰되 뒤에 {} 는 붙이지 않아도 된다.
profile
智(지)! 德(덕)! 體(체)!

0개의 댓글