-
스나이퍼팩토리 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.@overrideWidget 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;
@overrideState<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++;});}
@overrideWidget 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로, 한번 정해졌으므로 이제부터는 변경이 불가능하다.
@overrideState<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 객체의 상태가 변경되었다는 것을 알린다.
@overrideWidget 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을 쓰는게 좋다.
[참고]