제어자는 클래스, 변수, 함수를 정의할때 함께 쓰여서 이것들을 사용하기 위한 옵션을 정의해주는 역할
void main(){
final int myFinal = 30;
const int myConst = 70;
}
접근제어자
final,const : 변수 값이 한번 초기화되면 바꿀 수 없게 하는 것
void main(){
final int myFinal = 30;
const int myConst = 70;
myFinal = 20; // 에러
myConst = 50; // 에러
}
final 변수 초기화
선언할때 초기화
void main(){
final int myFinal = 30;
}
객체 생성시에 외부데이터를 받아 생성자를 통해 초기화
class Person {
final int age;
String name;
Person(this.age, this.name);
}
void main(){
Person p1 = new Person(21, 'Tom'); // 생성자를 통해 할당 -> 이후로 age는 변경 불가
print(p1.age); // 21
}
2번이 가능한 이유
final은 초기화되는 시점이 앱이 실행되는 시점이기 때문 ⇒ run time constant
response 변수는 컴파일시에 초기화 되지 않고 앱이 실행된 후 웹 상에서 데이터가 전송될 때까지 기다렸다가 그 후에 값이 저장
Const
compile-time constant는 컴파일 시에 상수가 됨
const 변수는 선언과 동시에 초기화
void main(){
const time = DateTime.now() // 에러
}
현재 시간은 매번 호출될 때마다 그 값이 변경되기 때문에 런타임시에 값이 지정되어야하므로 const 키워드는 오류 발생
정리
const 변수는 컴파일 시에 상수화
final 변수는 런타임 시에 상수화
Compile-time constant = Run-time constant 컴파일 시에 상수화는 런타임에도 상수화가 유지됨을 의미
먼저, StatefulWidget클래스는 아래와 같이 widget 클래스를 상속하고 있습니다.
abstract class StatefulWidget extends Widget {
const StatefulWidget({ Key? key }) : super(key: key);
@override
StatefulElement createElement() => StatefulElement(this);
@protected
@factory
State createState(); // ignore: no_logic_in_create_state, this is the original sin
}
widget클래스는 기본적으로 immutable 즉, 한번 생성되면 state가 변하지 않습니다.
MyApp Stateful widget을 만나면 관련된 MyApp Stateful element를 추가하지만 createState 메서드를 호출해서 MyApp Stateful element와 연결된 MyAppState 객체도 생성합니다.
그런데 이 객체는 MyApp Stateful widget과 간접적으로만 연결되어 있습니다.
여기서 특이점은 MyApp Stateful element는 위젯 관련 중요 정보들을 가지고 있지만, 메모리 상에서 어디에도 종속되지 않는 독립된 객체로서 MyAppState 객체에 대한 정보도 가지게 되는 것입니다.
이제 setState메서드가 호출되고 build 메서드로 인해서 state객체가 rebuild 되면서 새로운 state를 반영한 새로운 MyApp Stateful widget이 rebuild 됩니다. 그러면 MyApp Stateful element에 연결되어 있는 MyAppState객체에 새로운 state가 저장이 되고 이제 MyAppState객체는 새롭게 rebuild된 MyAppStateful widget을 가리키게 됩니다.
왜 MyAppState 객체는 MyAppStateful widget처럼 widget tree상에서 매번 rebuild되지 않는 것일까?
비용문제
state가 변한 state 객체를 비용이 싼 Stateful widget으로 만들어서 계속 rebuild하고 MyAppState 객체는 element tree에서 mutable하게 존재하면서 필요할때마다 새로운 state를 저장함과 동시에 새롭게 rebuild된 Stateful Widget과의 링크만을 업데이트 해줍니다.
import 'dart:io';
Future<String> download(){
// Future는 빈박스이다.
// 먼저 value는 빈박스(null)를 만들고 5초뒤 return을 받음
Future<String> value = Future.delayed(Duration(seconds:5),(){
return '사과'; // 5초뒤에 return을 받음
});
return value; // Futurn data는 Future로 받아야함
}
// 첫번째 방법
// await를 사용하기 때문에 async 키워드 필요
main() async {
//빈박스를 먼저 받아오기 때문에 Future로 받아야함
//그렇기에 기다릴 필요가 있음 -> await 사용 -> async 키워드 필요
// Future<String> value = download();
// 기다렸다 받기 때문에 Future로 받을 필요없음
String value = await download();
print(value);
}
// 두번째 방법
main(){
download().then((value){
// 빈박스가 채워져야 실행됨
print(value);
});
//메인 종료 후 download return 받음
}
Isolate
동시에 실행
void download(var msg){
Future((){
for(int i = 0; i < 5; i++){
sleep(Duration(seconds:1));
print("download함수 : ${i}");
}
});
}
main(){
// 독립적인 스레드
Isolate.spawn(download,'msg');
for(int i = 0; i < 5; i++){
sleep(Duration(seconds:1));
print("main함수 : ${i}");
}
}