ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 스나이퍼팩토리 8일차 과제1
    카테고리 없음 2023. 2. 3. 23:59

    과제1

    플러터에서 제공하는 아주 기본적인 소스코드의 동작원리와 Stateful를 사용하는 이유

     

    기본 main.dart코드

    import 'package:flutter/material.dart';

    void main() {
      runApp(const MyApp());
    }

    class MyApp extends StatelessWidget {
      const MyApp({super.key});

      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            // This is the theme of your application.
            //
            // Try running your application with "flutter run". You'll see the
            // application has a blue toolbar. Then, without quitting the app, try
            // changing the primarySwatch below to Colors.green and then invoke
            // "hot reload" (press "r" in the console where you ran "flutter run",
            // or simply save your changes to "hot reload" in a Flutter IDE).
            // Notice that the counter didn't reset back to zero; the application
            // is not restarted.
            primarySwatch: Colors.green,
          ),
          home: const MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }

    class MyHomePage extends StatefulWidget {
      const MyHomePage({super.key, required this.title});

      // This widget is the home page of your application. It is stateful, meaning
      // that it has a State object (defined below) that contains fields that affect
      // how it looks.

      // This class is the configuration for the state. It holds the values (in this
      // case the title) provided by the parent (in this case the App widget) and
      // used by the build method of the State. Fields in a Widget subclass are
      // always marked "final".

      final String title;

      @override
      State<MyHomePage> createState() => _MyHomePageState();
    }

    class _MyHomePageState extends State<MyHomePage> {
      int _counter = 0;

      void _incrementCounter() {
        setState(() {
          // This call to setState tells the Flutter framework that something has
          // changed in this State, which causes it to rerun the build method below
          // so that the display can reflect the updated values. If we changed
          // _counter without calling setState(), then the build method would not be
          // called again, and so nothing would appear to happen.
          _counter++;
        });
      }

      @override
      Widget build(BuildContext context) {
        // This method is rerun every time setState is called, for instance as done
        // by the _incrementCounter method above.
        //
        // The Flutter framework has been optimized to make rerunning build methods
        // fast, so that you can just rebuild anything that needs updating rather
        // than having to individually change instances of widgets.
        return Scaffold(
          appBar: AppBar(
            // Here we take the value from the MyHomePage object that was created by
            // the App.build method, and use it to set our appbar title.
            title: Text(widget.title),
          ),
          body: Center(
            // Center is a layout widget. It takes a single child and positions it
            // in the middle of the parent.
            child: Column(
              // Column is also a layout widget. It takes a list of children and
              // arranges them vertically. By default, it sizes itself to fit its
              // children horizontally, and tries to be as tall as its parent.
              //
              // Invoke "debug painting" (press "p" in the console, choose the
              // "Toggle Debug Paint" action from the Flutter Inspector in Android
              // Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
              // to see the wireframe for each widget.
              //
              // Column has various properties to control how it sizes itself and
              // how it positions its children. Here we use mainAxisAlignment to
              // center the children vertically; the main axis here is the vertical
              // axis because Columns are vertical (the cross axis would be
              // horizontal).
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                const Text(
                  'You have pushed the button this many times:',
                ),
                Text(
                  '$_counter',
                  style: Theme.of(context).textTheme.headlineMedium,
                ),
              ],
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _incrementCounter,
            tooltip: 'Increment',
            child: const Icon(Icons.add),
          ), // This trailing comma makes auto-formatting nicer for build methods.
        );
      }
    }

    아래는 기본소스코드 실행결과.

    기본소스코드 실행결과

    ● 코드이해하기

    import 'package:flutter/material.dart';

    material design ( MaterialApp() ) 을 사용하기 위한 플러터의 기본 패키지이다.
    유사품으로 애플 디자인의 cupertino.dart가 있다.

     
    void main() {runApp(const MyApp());:Myapp위젯(이름을 마음대로 지정 가능,직접 만들어야 됨) 기본적으로 실행하기 위해 꼭 필요한 커스텀위젯, 최상위 함수가 최초로 불러온 위젯으로 위젯트리에서 최상위에 위치한다.
     
    class MyApp extends StatelessWidget {
      const MyApp({super.key}); : class 인 MyApp은 StatelessWidget을 상속한다. StatelessWidget을 상속한다는 것은, 해당 위젯의 모든 것이 immutable 즉 변경할 수 없고, 모든 값은 final로 변경할 수 없다. 변화가 없는 StatelessWidget으로 정적인 위젯으로 만든다.
     
     
    @override
    상속받은 클래스의 메소드를 재정의한다. 즉, MyApp 클래스는 StatelessWidget의 Widget build() 을 재정의한다.
     
      Widget build(BuildContext context) {
        return MaterialApp(  //Flutter material 라이브러리를 사용하는 기능을 가진 위젯인 materialApp이 return되도록 작성한다. 위젯트리는 두 번째에 위치하고 모든 위젯을 감싸는 위치에 있다.
          title: 'Flutter Demo',   //Flutter Demo라는 이름을 가짐
          theme: ThemeData(   //ThemeData위젯: 앱의 기본적인 디자인 테마
            primarySwatch: Colors.blue,    :앱에서 기본적으로 사용할 색상견본
          ),
          home: const MyHomePage(title: 'Flutter Demo Home Page'),  //앱을 실행했을 때 가장 먼저 보이는 화면
        );
      }
    class MyHomePage extends StatefulWidget {  //StatefulWidget을 상속받는다.
      const MyHomePage({super.key, required this.title});  
      final String title;

    StatefulWidget

    StatefulWidget은 변경가능한 상태를 가진 위젯이다. Widget이 빌드될 때 동기적으로 읽거나, 생명주기동안 변경될 수 있는 정보가 있다면 사용하는 것이 좋다.

    MyHomePage 생성자는 key와 title을 가지는데, required 가 붙었으므로 title은 반드시 인자로 가져야 한다.
    key는, 저번과 같이 상위 클래스의 key를 상속받는데, null일 수도 있다.

    title은 final로, 한번 정해졌으므로 이제부터는 변경이 불가능하다.

     

    @override
    State<MyHomePage> createState() => _MyHomePageState();}

    Stateful Widget은 createState() 메소드에서 생성한 객체를 반환해야 한다. 그리고 StatefulWidget 안이 아닌, State 클래스에 build 메소드가 있다.

    StatelessWidget은 build 메서드에서 생성한 객체를 바로 반환하지만 StatefulWidget은 이 createState() 메서드에서 생성한 객체를 반환한다는 것.

    -> _MyHomePageState() 에서 build가 진행 될 것이다.

     

    class _MyHomePageState extends State<MyHomePage> {
      int _counter = 0;

      void _incrementCounter() {
        setState(() {
          _counter++;
        });
      }

    dart에서 이름의 맨 앞에 _이 붙는다는 것은, private 속성을 가진 것이라고 보면 된다.

    void incrementCounter() 라는 함수를 정의한다.
    해당 함수가 실행되면, setState()를 통해 Widget이 다시 rebuild(정확히는, build 메소드가 재실행)되고, _counter 의 값이 1 올라간다.

    setState() -> State 객체의 상태가 변경되었다는 것을 알린다.

    @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),       //앱바에는 제목인  Flutter Demo HomePage가 들어간다.
          ),
          body: Center(          //가운데위치
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,    //가운데 정렬
              children: <Widget>[
                const Text(
                  'You have pushed the button this many times:',
                ),
                Text(
                  '$_counter',     
                  style: Theme.of(context).textTheme.headlineMedium,
                ),
              ],
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _incrementCounter,    //누르면 _incrementCounter함수 실행
            tooltip: 'Increment',    //탭툴은 커서를 가져다 대면 해당 설명이 나온다.
            child: const Icon(Icons.add),
          ), 
        );
      }
    }

    위에는 화면구성 코드다.

     

    즉, 플러팅버튼 (+)을 누르면 숫자텍스트가 +1씩 올라가는걸 볼 수 있다.


    Stateful Widget이 사용되어야 하는 이유

    위에 설명했듯 StatefulWidget은 변경가능한 상태를 가진 위젯이다. Widget이 빌드될 때 동기적으로 읽거나, 생명주기동안 변경될 수 있는 정보가 있다면 사용하는 것이 좋다. 

    기본소스코드는 플로팅버튼을 누르는 이벤트가 있으면 텍스트위젯이 변경되는 상황이 되어야 한다. 그러므로 StatefulWidget을 사용해야 한다. 

    StatelessWidget이 StatefulWidget보다 성능이 좀 더 나아서 굳이 필요없다면 StatelessWidget을 쓰는게 좋다.

     

     

    [참고]

    https://velog.io/@1984/Flutter-%EA%B8%B0%EB%B3%B8-%EC%98%88%EC%A0%9C-%EC%84%A4%EB%AA%85-%EB%B0%8F-%ED%95%B4%EC%84%A4

Designed by Tistory.