본문 바로가기

그 땐 App했지/그 땐 Flutter했지

[TAVE/Study] Do it! Flutter 2장 다트를 알면 플러터가 보인다

728x90

210914 화

일단 지금은 새벽 1시고 이따 저녁 8시에 스터디! 있다!

아까 다 공부하려고 했는데! 실패했다!

그래도... 앞부분이면 쉽..지 않을까? 18장이던데... 다 끝내기 목표임👊🏻

 

다트의 특징

1. main() 함수로 시작

//함수 정의
printInteger(int aNumber) {
  print('The number is $aNumber.');
}

//main() 함수에서 시작
main(){
  var number = 42; //var는 자료형을 특정하지 않음
  printInteger(number);
}

2. 어디에서나 변수를 선언하거나 사용 가능

3. 모든 변수가 객체

4. 자료형이 엄격, dynamic타입은 여러 자료형 허용

구분 자료형 설명
숫자 int 정수형
double 실수형
num 정수 or 실수
문자열 String 문자
불리언 bool True or False
자료형 추론
(입력받은 값에 따라 자료형 결정)
var 한 번 결정된 자료형은 변경 불가
dynamic 다른 변수 입력하면 자료형 변경 가능

5. 제네릭 타입 이용 가능

6. public, protected 키워드 없음, 외부로 노출하고 싶지 않을 땐 _ 사용

7. 변수, 함수의 시작은 _나 문자열

8. 삼항 연산자(3개의 피연산자를 취하는 유일한 연산자) 사용 가능

var visibility = isPublic ? 'public' : 'private';
String playerName(String name) => name ?? 'Guest';

9. Null safety 지원 - 널 예외를 코드 단계에서 구분하기 위함

  • 자료형 다음에 ?를 붙이면 Null 가능, 붙이지 않으면 불가능
  • !를 붙이면 Null이 아님을 직접 표시
int? couldReturnNullButDoesnt() => -3; //null을 넣을 수 있음

void main() {
  int? couldBeNullButIsnt = 1; //null로 변경 가능
  List<int?> listThatCouldHoldNulls = [2, null, 4]; //List의 int에 null 값 포함 가능
  List<int>? nullsList; //List 자체가 null일 수 있음
  
  int a = couldBeNullButIsnt; //null 넣으면 오류
  int b = listThatCouldHoldNulls.first; //int b는 ?가 없어서 오류
  int b = listThatCouldHoldNulls.first!; //null이 아님을 직접 표시
  int c = couldReturnNullButDoesnt().abs(); //null일 수도 있으므로 abs()에서 오류
  int c = couldReturnNullButDoesnt()!.abs(); //null이 아님을 직접 표시
  
  print('a is $a.');
  print('b is $b.');
  print('c is $c.');
}

 

비동기 처리방식

비동기: 언제 끝날지 모르는 작업을 기다리지 않고 다음 작업을 처리하는 것

다트는 asyncawait 키워드 이용

void main() {
  checkVersion();
  print('end process');
}
Future checkVersion() async {
  var version = await lookUpVersion();
  print(version);
}

int lookUpVersion() {
  return 12;
}
//실행 결과
end process
12

👉🏻 checkVersion() 함수 앞뒤로 Futureasync를 붙여 비동기로 만들었다.

void main() async {
  await getVersionName().then((value) => {
    print(value)
  });
  print('end process');
}

Future<String> getVersionName() async {
  var versionName = await lookUpVersionName();
  return versionName;
}

String lookUpVersionName() {
  return 'Android Q';
}
//실행 결과
Android Q
end process

👉🏻 then() 함수: 비동기 함수가 반환하는 값을 처리한다.

+ error() 함수: 실행과정에서 오류가 발생하면 이를 이용해 예외처리 한다.

 

다트와 스레드
void main() {
  printOne();
  printTwo();
  printThree();
}

void printOne() {
  print('One');
}

void printThree() {
  print('Three');
}

void printTwo() async {
  Future.delayed(Duration(seconds: 1), (){
    print('Future!!');
  });
  print('Two');
}
//실행 결과
One
Two
Three
Future!! //1초 뒤에 나옴

👉🏻 Future.delayed() 함수: Duration 기간 동안 기다린 후에 진행

 

void main() {
  printOne();
  printTwo();
  printThree();
}

void printOne() {
  print('One');
}

void printThree() {
  print('Three');
}

void printTwo() async {
  await Future.delayed(Duration(seconds: 2), (){
    print('Future Method');
  });
  print('Two');
}
//실행 결과
One
Three
Future Method //2초 뒤에
Two

👉🏻 printTwo함수에 await를 붙였으니 잠시 멈추고 main의 남은 함수를 실행 후에 printTwo()함수 실행

 

JSON 데이터

서버와 데이터를 주고 받을 때 사용하는 형식으로 가장 편리하고 파일 크기가 작다.

소스에 convert라는 라이브러리를 포함해야 한다.

import 'dart:convert';

void main() {
  var jsonString = '''
  [
    {"score": 40},
    {"score": 80}
  ]
  ''';
  var scores = jsonDecode(jsonString);
  print(scores is List); //true 출력
  var firstScore = scores[0];
  print(firstScore is Map); //true 출력
  print(firstScore['score'] == 40); //true 출력
}
//실행 결과
true
true
true

👉🏻 jsonDecode() 함수: JSON 형태의 데이터를 dynamic 형식의 리스트로 변환해서 반환

map: 키와 값이 있는 형태

import 'dart:convert';

void main() {
  var scores =[
    {"score": 40},
    {"score": 80},
    {"score": 100, 'overtime': true, 'special_guest': null}
  ];
  
  var jsonText = jsonEncode(scores);
  print(jsonText ==
    '[{"score": 40},{"score": 80},'
    '{"score": 100, "overtime": true,'
    '"special_guest": null}]'); //true 출력
 }

👉🏻 jsonEncode() 함수: 앱에서 서버로 데이터를 보낸다.

이 때 키 값(score)은 큰따옴표로 묶이고 전체 데이터를 작은 따옴표로 한 번 묶어 JSON형태로 만든다.

 

스트림 통신하기

스트림: 처음 넣은 데이터를 가장 먼저 꺼내는 데이터 구조로 순서를 보장받고 싶을 때 이용한다.

import 'dart:async';

Future<int> sumStream(Stream<int> stream) async {
  var sum = 0;
  await for (var value in stream) {
    print('sumStream : $value');
    sum += value;
  }
  return sum;
}

Stream<int> countStream(int to) async* {
  for (int i = 1; i <= to; i++) {
    print('countStream : $i');
    yield i;
  }
}

void main() async {
  var stream = countStream(10);
  var sum = await sumStream(stream);
  print(sum); //55
 }
//실행 결과
countStream : 1
sumStream : 1
countStream : 2
sumStream : 2
//(...생략...)
countStream : 9
sumStream : 9
countStream : 10
sumStream : 10
55

👉🏻 countStream(): async*과 yield로 비동기 함수로 만들었다.

async*는 앞으로 yield를 이용해 지속석으로 데이터를 전달하겠다는 의미이다.

main() {
  var stream = Stream.fromIterable([1, 2, 3, 4, 5]);
  
  //가장 마지막 데이터의 결과: 5
  stream.last.then((value) => print('last: $value'));
 }
728x90