Flutter

Dart 문법 정리

juyeong.lee 2019. 12. 21. 21:35
반응형

String

void main() {
	print('Hello World');
	print("Hello World");
}

작은 따옴표, 큰 따옴표 모두 가능

 

변수

void main() {
	var a = 10;
	var str = 'Hello';
	var b = 3.5;
	var isMarried = true;
}

Dart에서는 타입을 추론하기 때문에 var로 통일 가능

 

dynamic

void main() {
	dynamic c = 10;
    
	myPrint(10);
}

myPrint(dynamic str) {

}

일반적인 변수를 사용하는 경우 var

dynamic은 다른 함수와 같이 사용할 때

Java의 Object 같은 느낌

 

num

void main() {
	int n = 10;
	// double d = n; // Java는 자동으로 type casting 되어 컴파일에 이상이 없다.

	// Flutter는 무조건 type casting 해 줘야 함
	num d = n; // type을 num으로 해 주면 int, double 상관없이 사용가능
}

myPrint(num str) {

}

num은 int와 double을 포함한다.

JSON 데이터를 통해서 온도에 대한 값을 읽어왔는데 어떨 때는 18, 어떨 때는 18.5일 때 둘 다 받아오려면 num 사용해야 한다.

 

final

void main() {
	final e = 10;
}

Java와 동일하지만 type을 쓰지 않아도 된다.

한 번 초기화되면 변경할 수 없는 값

 

const

void main() {
	final a = 10;
	const b = 20;
}

const와 final은 모두 값 변경이 불가능하다.

const는 컴파일 타임의 상태, 즉 메모리에 이미 저장이 되어 버린 것

final은 동적으로 메모리에 할당됨

const는 재사용을 많이 해야하는 케이스(Padding 등)에 유용하다.

 

Collection

void main() {
	List<String> items = ['a', 'b', 'c'];
	var items = [1, 2, 3];

	print(items);

	// List에 접근하는 방법은 Java에서 배열에 접근하는 방법과 동일하다. (Dart에는 배열이 없음)
	print(items[0]);
}

 

Set

void main() {
	var items = [1, 2, 3]; // 배열 형태로 사용하면 List

	var itemSet = {1, 2, 3};
	print(itemSet);
}

 

Map

void main() {
	var itemMap = {
		'key1': 1,
		'key2': 2,
		'key3': 3,
	};

	print(itemMap);
}

JSON 형태로 만들면 Map

 

spread 연산자(...)

void main() {
	var itmes = [1, 2, 3];

	var items2 = [...items, 4, 5];

	print(items2); // [1, 2, 3, 4, 5]
}

 

메소드

void main() {
	thing('홍길동');
	something('홍길동', age: 20);
}

void thing(String name, {int age = 10}) { // {option = default}

}

void something(String name, {@required int age}) {

}

 

메소드는 Dart에서 1급 객체(parameter로 전달할 수 있는 객체)

class MainPage extends StateefulWidget {
	@override
	_MainPageState createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
	void something() {

	}

	@override
	Widget build(BuildContext context) {
		return Container(
		  child: RaisedButton(onPressed: something, // 이름만 써도 됨(1급 객체 취급)
          
		  ) // RaisedButton
		); // Container
	}
}

 

type 비교(is, is not)

void main() {
	var a = 10;
    
	if (a is int) {
		print('정수');
	}

	if (a is! int) {
		print('정수가 아님');
	} else {
		print('정수');
	}
}

 

type cast

void main() {
	var a = 10;
	var b = 3.5;

	b = a as double;
}

 

??

void main() {

	String name;

	print(name); // null

	// null일 때 기본값을 주고 싶으면
	print(name ?? '널');

	// name이 null이 아닐 때만 실행
	print(name?.toLowerCase());

}

 

Class

void main() {
	var person = Person('홍길동', age: 10); // new 키워드 생략 가능
}

class Person {
	String name;
	int age;

	Person(this.name, {this.age}); // Constructor
}
void main() {
	var person = Person('홍길동');
	print(person.name); // 제 이름은 홍길동
}

class Person {
	String _name; // private
	int _age;

	String get name => '제 이름은 $_name'; // 람다식
}

 

 

void main() {
	var person = Person();
	person.setName('홍길동');
	person.setAge(10);

	var person2 = Person()
	  ..setName('홍길동')
	  ..setAge(10);

}

class Person {
	String name;
	int age;

	void setName(String name) {
		this.name = name;
	}

	void setAge(int age) {
		this.age = age;
	}
}
class Employee implements Person { // interface처럼 사용 가능함
	// 다 override 강제로 해야 함

}

class Person {
	String name;
	int age;

	void setName(String name) {
		this.name = name;
	}

	void setAge(int age) {
		this.age = age;
	}
}

implements를 사용하면 override 강제로 해야 함

class Employee with Person {

	@override
	void setName(String name) {

	}
}

class Person {
	String name;
	int age;

	void setName(String name) {
		this.name = name;
	}

	void setAge(int age) {
		this.age = age;
	}
}

선택적으로 override 하고 싶을 때 with를 사용하면 된다. (Dart의 mixin 기능)

 

Future

클릭을 했는데 이 안에서 네트워크 요청을 해야 하면 그 요청은 비동기로 실행될 것이고, 언제 끝나는지는 모른다.

그런 메소드들은 모두 future 형태

void main() {
	print('시작');
	networkRequest(); // 비동기로 요청
	print('끝');
}

Future<void> networkRequest() async {
	print('네트워크 요청 시작');
	await Future.delayed(Duration(seconds: 3));
	print('네트워크 요청 끝'); // 3초 후에 나오게 된다.

	return; // 생략 가능
}

 

StreamBuilder

setState는 전체를 다시 build 한다. 중간에 로직이 껴 있을 때 쓸데없이 호출되는 경우가 있음.

import 'dart:async';

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

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

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

StreamBuilder를 이용하면 해당 부분만 다시 그려진다. 성능 등 여러가지 면에서 좋다.

import 'dart:async';

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  var _counterController = StreamController<int>()..add(0);

  void _incrementCounter() {
    _counter++;
    _counterController.add(_counter);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            StreamBuilder<int>(
              stream: _counterController.stream,
              builder: (context, snapshot) {
                return Text(
                  '${snapshot.data}',
                  style: Theme.of(context).textTheme.display1,
                );
              }
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

 

주석

/// : 정보가 보인다. 클래스나 메소드 문서화를 하고 싶을 때 사용

반응형

'Flutter' 카테고리의 다른 글

[Mac] Flutter 설치  (0) 2019.12.18