Dandy Now!
  • [Flutter] "Do it! 플러터 앱 프로그래밍" - 플러터 프로젝트 구조 | main.dart , 위젯의 생명주기
    2022년 02월 10일 23시 56분 44초에 업로드 된 글입니다.
    작성자: DandyNow
    728x90
    반응형

    플러터 프로젝트 구조

    "조준수. (2021). Do it! 플러터 앱 프로그래밍. 이지스퍼블리싱", 3장을 공부하였다. main.dart 파일의 구조를 뜯어보았고, 그 과정에서 Switch, ElevatedButton을 맛보았다. 마지막으로 위젯의 생명주기를 살펴보았는데 플러터를 이해함에 있어 매우 중요한 개념으로 보인다.

     

    Do it! 플러터 앱 프로그래밍

    플러터 기본 & 고급 위젯은 물론오픈 API와 파이어베이스를 이용한 앱 개발부터 배포까지!플러터 SDK 2.x 버전을 반영한 개정판!이 책은 플러터의 기초부터 고급 활용법까지 다루어 다양한 영역에

    book.naver.com

     

    플러터 메인 소스 파일(main.dart)

    Hello Flutter

    // main.dart
    import 'package:flutter/material.dart'; // material.dart 패키지는 플러터의 UI 관련된 거의 모든 클래스를 포함하고 있다. 자주 사용한다.
    
    void main() {
      runApp(MyApp());
    }
    
    // StatelessWidget 정적, 내용을 갱신할 필요가 없는 위젯이다.
    // StatefullWidget 동적, 앱이 위젯의 상태를 감시하다가 위젯이 특정 상태가 되면 알맞은 처리를 수행한다. 상태 변경을 감시하므로 리소스를 많이 사용한다.
    class MyApp extends StatelessWidget {
      @override // 상속한 StatelessWidget의 build 함수를 재정의 한다.
      // build 함수는 어떤 위젯을 만들 것인지 정의한다.
      Widget build(BuildContext context) {
        // MaterialApp 함수를 반환한다. MaterialApp 함수는 그림 그릴때 필요한 도화지라고 생각하면 된다.
        return MaterialApp(
          title: 'Flutter Demo', // 앱의 이름을 지정한다.
          // 앱의 테마를 지정한다.
          theme: ThemeData(
            primarySwatch: Colors.blue, // 메인 색상을 지정한다.
            visualDensity: VisualDensity
                .adaptivePlatformDensity, // 모바일, 웹, 데스크톱, 맥 등 어떤 플랫폼에서든 자연스럽게 보이도록 지원한다.
          ),
          // home: const MyHomePage(title: 'Flutter Demo Home Page'), // home은 앱이 실행될 때 첫 화면에 표시할 내용을 지정한다.
          // home: Text('hello\nFlutter'), // 검은 배경(기본 배경색)의 좌측 상단(그리기 시작점)에 출력된다. 플러터가 화면을 그리는 순서는 "좌우상하"이다.
          // home: Center( // Center 함수를 호출하고 child 옵션에 Text 함수를 넣었다.
          //   child: Text('hello\nFlutter', textAlign: TextAlign.center), // 출력 텍스트가 화면 중앙에 위치하게 된다.
          // ));
          // 배경을 변경하기 위해서는 Container 함수가 필요하다.
          home: Container(
            color: Colors.white, // 흰색 배경으로 변경된다.
            child: Center(
              child: Text('hello\nFlutter',
                  textAlign: TextAlign.center,
                  // TextStyle은 글자색과 크기 등을 변경할 수 있다.
                  style: TextStyle(
                      color: Colors.blue,
                      fontSize: 20)),
            ),
          ),
        );
      }
    }

     

    [그림 1] Hello Flutter

     


     

    Switch

    // main.dart
    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatefulWidget {
      @override
      State<MyApp> createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> {
      // 언더스코어(_)는 main.dart 내부에서만 사용할 수 있다는 의미이다.
      var switchValue = false;
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          darkTheme: ThemeData.light(),
          // Scaffold 클래스 이용해 머티리얼 디자인을 적용한다.
          home: Scaffold(
            body: Center(
              // 스위치 적용하였다. StatelessWidget 상태에서는 작동하지 않는다.
              child: Switch(
                  value: switchValue,
                  // 스위치를 누르면 onChanged 이벤트가 발생, value 값(true/false)이 switchValue 변수에 할당, Switch의 value 값 변경되면서 화면이 갱신된다.
                  onChanged: (value) {
                    // setState 함수는 변숫값이 변경된 사실을 앱에 알려 화면을 갱신해 준다. 비로소 스위치 켜짐/꺼짐 표현이 된다.
                    setState(() {
                      print(value);
                      switchValue = value;
                    });
                  }),
            ),
          ),
        );
      }
    }

     

    [그림 2] 좌 - false, 우 - true

     


     

    ElevatedButton

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatefulWidget {
      @override
      State<MyApp> createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> {
      var switchValue = false;
      String test = 'hello'; // 버튼 내 텍스트
      Color _color = Colors.purple; // 최초 버튼 색
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.purple,
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          darkTheme: ThemeData.light(),
          home: Scaffold(
            body: Center(
              // ElevatedButton 위젯으로 버튼을 만든다.
              child: ElevatedButton(
                child: Text('$test'),
                style:
                    ButtonStyle(backgroundColor: MaterialStateProperty.all(_color)),
                onPressed: () {
                  // if (test == 'flutter') { // 조건에 _color 대신 test를 줄수도 있다.
                  if (_color == Colors.blue) {
                    setState(() {
                      test = 'hello';
                      _color = Colors.purple;
                    });
                  } else {
                    setState(() {
                      test = 'flutter';
                      _color = Colors.blue;
                    });
                  }
                },
              ),
            ),
          ),
        );
      }
    }

     

    [그림 3] ElevatedButton 적용

     


     

    위젯의 생명주기

    특정 화면에서 계속 소리가 나는 위젯이 있다고 할때 종료 시 소리도 함께 멈춰야 한다. 이처럼 위젯의 생명주기를 고려해야 앱의 동작이나 자원을 효율적으로 관리할 수 있다.

    순서 생명주기 내용
    1 createState() 처음 Statefull을 시작할 때 반드시 호출
    위젯의 상태 생성
    다른 생명주기 함수들이 포함된 State 클래스 반환
    2 mounted == true createState() 함수가 호출되면 true
    위젯을 제어할 수 있는 buildContext 클래스에 접근 가능
    buildContext가 활성화되어야 setState() 함수 사용 가능
    3 initState() 위젯을 초기화할 때 한 번만 호출
    _getJsonData() 함수 호출해 서버에서 받은 데이터를 화면에 출력 가능
    4 didChangeDependencies() 상속 받은 위젯을 사용할 때 피상속자가 변경되면 호출(의존성이 변경되면 호출)
    5 build() ㆍ위젯을 반환(화면에 렌더링)
    6 didUpdateWidget() 위젯을 변경할 때 호출
    initState() 함수는 위젯을 초기화할 때 한 번만 호출되므로 이 위젯이 필요함
    7 setState() 위젯의 상태를 갱신함
    데이터 변경을 알림
    변경된 데이터를 UI에 적용하기 위해 필요함
    8 deactivate() State 객체가 플러터 구성 트리로 부터 제거될 때 호출
    메모리에는 남아 있어서 재사용 가능
    9 dispose() State 완전 제거(해당 위젯을 종료한다는 뜻)
    위젯을 소멸할 때 꼭 호출해야 하는 함수라면 이 함수 안에서 호출해야 함
    10 mounted == false 모든 프로세서 종료되면 false(State 재사용 불가)

     

    ※ State와 StatefullWidget 클래스를 나누어 놓은 이유 : StatefullWidget 보다 State 클래스가 더 무겁기 때문이다. 평소에 StatefullWidget로 감시하다가 상태 변경 신호가 오면 State 클래스가 화면을 갱신한다.

    728x90
    반응형
    댓글