Functional programming
- 프로그램을 함수들로 구성하는 프로그래밍 패러다임
- 함수는 인자를 받아 결과를 반환하는 것으로 구성되며, 상태와 상태의 변화가 없는 함수를 사용하는 것을 권장
Iterable 데이터 타입에 활용할 수 있는 대표적인 function
1. Iterable 사이의 형 변환
- List → Map : asMap()
- .keys/.values → Iterable
- List → Set : toSet() 또는 Set.from(listName)
- 자동으로 중복 제거
- Map/Set → List : toList()
2. map
- 각 요소에 함수를 적용할 수 있으며, 각 요소를 새로운 값으로 대체해줌
- 단, 원본이 변경되는 것이 아니고 새로운 리스트를 만들어냄
- 함수의 파라미터로 함수를 전달 → map(() {}) 또는 map(() ⇒ ) 의 형태
//List에서 활용
void main() {
List<String> blackPink = ['로제', '지수', '리사', '제니'];
final newBlackPink = blackPink.map((x) {
return '블랙핑크 $x';
});
final newBlackPink2 = blackPink.map((x) => '블랙핑크 $x');
//newBlackPink,newBlackPink2의 데이터 타입은 Iterable<String>
print(blackPink == newBlackPink);
//false
print(newBlackPink == newBlackPink2);
//false
//Map에서 활용
Map<String, String> blackPink = {
'Rose': '로제',
'Jisu': '지수',
'Lisa': '리사',
'Jennie': '제니'
};
//key와 value 모두를 파라미터로 전달
//MapEntry: Map을 return 해주는 메소드
final result = blackPink
.map((key, value) => MapEntry('BlackPink member $key', '블랙핑크 멤버 $value'));
//key와 value을 따로 mapping 하고 싶을때
final key = blackPink.keys.map((x) => 'BP $x').toList();
final values = blackPink.values.map((x) => '블랙핑크 $x').toList();
//Set는 위의 예시와 동일하게 활용 가능
}
3. where
- 일종의 필터링 함수
- 특정 조건을 만족하는 요소를 찾을 수 있음
void main() {
List<Map<String, String>> people = [
{'name': '로제', 'group': '블랙핑크'},
{'name': '지수', 'group': '블랙핑크'},
{'name': 'RM', 'group': 'BTS'},
{'name': 'V', 'group': 'BTS'},
];
final blackPink = people.where((x) => x['group'] == '블랙핑크');
final bts = people.where((x) => x['group'] == '블랙핑크');
}
4. reduce와 fold
- 각각의 값들을 mapping 해가면서 그 값들의 total을 구할 때 활용
- 원본 리스트와 리턴되는 값의 데이터 타입이 동일해야함
- 데이터 타입이 다르다면 fold 사용
void main() {
List<int> numbers = [1, 3, 5, 7, 9];
//첫번째: list의 첫번째, 두번째 값이 각각 prev, next
//두번째: 이전의 return 값이 prev, list의 세번쨰 값이 next
final result = numbers.reduce((prev, next) => prev + next);
List<String> words = ['안녕하세요', '플러터', '스터디'];
final sentence = words.reduce((prev, next) => prev + next);
//error 발생
//words는 String, return 값은 int
words.reduce((prev, next) => prev.length + next.length);
//fold
//return 값이 무엇인지 generic하게 명시
//첫번째 파라미터가 첫번째 prev가 됨
numbers.fold<int>(0, (prev, next) => prev + next);
words.fold<int>(0, (prev, next) => prev + next.length);
}
5. spread operator
- 리스트 펼쳐넣기
- 여러개의 리스트를 합칠때 사용
- 형태는 같지만 완전히 다른 메모리에 할당됨
void main() {
List<int> even = [2, 4, 6, 8];
List<int> odd = [1, 3, 5, 7];
print([even, odd]); //[[2, 4, 6, 8], [1, 3, 5, 7]]
print([...even, ...odd]); //[2, 4, 6, 8, 1,3, 5, 7]
print(even == [...even]); //false
}
Asynchronous programming
- 프로그램이 요청한 작업이 완료되기를 기다리지 않고 또 다른 작업을 수행하는 것
- 장점:
- 전체 작업 처리 시간 단축시킬 수 있음 -> 성능, 응답성 향상
- 시스템 자원을 효율적으로 사용할 수 있음
- 예시:
- 서버에 작업 요청
- 네트워크를 통해 데이터 가져오기
- 데이터베이스에 쓰기
- 파일에서 데이터 읽기
- 비동기 프로그래밍을 하지 않으면 이전의 작업이 완료될 때까지 기다려야 하므로, 시스템이 응답하지 않는 것 처럼 보일 수 있음
- 장점:

Future
- 비동기 작업의 결과를 나타내며, Uncompleted와 Completed 라는 2가지 상태를 가짐

- delayed
- 1번 파라미터: 지연할 시간 Duration
- 2번 파라미터: 지연 시간이 지난 후 실행할 함수
//Synchronos
void main() {
addNumbers(1, 1);
addNumbers(2, 2);
}
void addNumbers(int number1, int number2) {
print('계산중: $number1 + $number2');
print('계산 완료: ${number1 + number2}');
}
//Asynchoronous programming
void main() {
addNumbers(1, 1);
addNumbers(2, 2);
}
void addNumbers(int number1, int number2) {
print('계산시작: $number1 + $number2');
Future.delayed(Duration(seconds: 2), () {
print('계산완료: $number1 + $number2 = ${number1 + number2}');
});
print('함수완료: $number1 + $number2');
}
///결과
///계산시작: 1 + 1
///함수완료: 1 + 1
///계산시작: 2 + 2
///함수완료: 2 + 2
///계산완료: 1 + 1 = 2
///계산완료: 2 + 2 = 4
- Future function
- 함수의 본문 앞에 async 키워드를 추가
- 해당 작업이 끝나기까지 기다릴 코드에 await 키워드를 추가
- await 키워드는 async 함수 내에서만 사용 가능
- addNumber 함수 내에서, await 함수를 기다려서 계산 시작 → 계산 완료 → 함수 완료 순서로 출력
- 그러나 전체 코드의 관점에서 보면 await를 기다리는 동안 수행할 수 있는 다음 코드를 수행하여
addNumbers(1, 1)이 끝나기 전에 addNumbers(2,2)가 수행됨
void main() {
addNumbers(1,1);
addNumbers(2,2);
}
void addNumbers(int number1, int number2) async {
print('계산시작: $number1 + $number2');
await Future.delayed(Duration(seconds: 2), () {
print('계산완료: $number1 + $number2 = ${number1 + number2}');
});
print('함수완료: $number1 + $number2');
}
///결과
///계산 시작: 1 + 1
///계산 시작: 2 + 2
///계산완료: 1 + 1 = 2
///함수완료: 1 + 1
///계산완료: 2 + 2 = 4
///함수완료: 2 + 2
- addNumber(1, 1)이 끝난 후, addNumbers(2,2)가 실행되도록 하기 위해서는 addNumbers를 Future를 return 하는 함수로 만들고, await addNumber로 작성
void main() async {
await addNumbers(1,1);
await addNumbers(2,2);
}
Future<void> addNumbers(int number1, int number2) async {
print('계산시작: $number1 + $number2');
await Future.delayed(Duration(seconds: 2), () {
print('계산완료: $number1 + $number2 = ${number1 + number2}');
});
print('함수완료: $number1 + $number2');
}
///계산시작: 1 + 1
///계산완료: 1 + 1 = 2
///함수완료: 1 + 1
///계산시작: 2 + 2
///계산완료: 2 + 2 = 4
///함수완료: 2 + 2
Stream
- 일종의 비동기 Iterable
- 연속된 데이터를 listen()을 통해 비동기적으로 처리
- future: 사진에 적합/stream: 영상에 적합
- 일련의 비동기 이벤트, 요청시 다음 이벤트를 가져오는 대신 이벤트가 준비되었을 때 스트림이 이벤트가 있다는 것을 알려줌
- stream을 닫을 때까지 무한대로 결과값을 받아낼 수 있음
- 연속된 데이터를 listen()을 통해 비동기적으로 처리

- stream에서 이벤트를 받고싶을 때 listen()
import 'dart:async';
//단일 stream: single subscription
void main() {
//StrramController: stream에 이벤트를 직접 지정
final controller = StreamController();
final stream = controller.stream;
final streamListener1 = stream.listen((val) {
print('Listener 1: $val');
});
controller.sink.add(1);
controller.sink.add(2);
controller.sink.add(3);
}
//stream을 여러개 만들기: broadcast
void main() {
final controller = StreamController();
final stream = controller.stream.asBroadcastStream();
final streamListener1 = stream.listen((val) {
print('Listener 1: $val');
});
final streamListener2 = stream.listen((val) {
print('Listener 2: $val');
});
controller.sink.add(1);
controller.sink.add(2);
controller.sink.add(3);
}
- Stream function
- async → async*
- await → yield
- yield* : stream의 모든 결과값이 나올때까지 대기
import 'dart:async';
void main() {
playAllStream().listen((val) {
print(val);
});
}
Stream<int> playAllStream() async* {
yield* calculate(1);
yield* calculate(1000);
}
Stream<int> calculate(int number) async* {
for (int i = 0; i < 5; i++) {
yield i * number;
await Future.delayed(Duration(seconds: 1));
}
}
///결과
///0
///1
///2
///3
///4
///0
///1000
///2000
///3000
///4000
참고자료
- https://www.inflearn.com/course/dart-언어-입문
- https://dart.dev/codelabs/async-await#why-asynchronous-code-matters
- 모바일 앱 개발을 위한 다트&플러터 - 서준수 저(디지털북스)
'Group Study (2023-2024) > Flutter' 카테고리의 다른 글
[Flutter] 6주차 스터디_State management와 Deep linking (1) | 2023.12.23 |
---|---|
[Flutter] 5주차 스터디_Data Fetch와 Future Builder (1) | 2023.12.21 |
[Flutter] 4주차 스터디_StatefulWidget과 BuildContext (0) | 2023.11.27 |
[Flutter] 3주차 스터디_UI Challenge (0) | 2023.11.20 |
[Flutter] 2주차 스터디_Flutter 입문 (0) | 2023.11.13 |