본문 바로가기

study/flutter

Flutter -async

 

https://www.youtube.com/watch?v=vl_AaCgudcY

isolate

flutter은 단일 thread로 isolate라는 곳에서 이벤트 루프를 실행함.

isolate는 필요시 만들수 있지만 각각의 isolate는 서로 같은 메모리를 공유하진 않음.

단일쓰레드에서 공유도 안하기 때문에 메모리 할당이나 해제 등에 locking이 필요하지 않음.

 

그럼 dart는 어떻게 비동기 처리를 지원할까?

앱의 주기를 생각해보면 어떻게 진행될지 예측할 수 없다. 사용자의 입력이나 data from disk 등등

따라서 이벤트 루프를 활용한다. 이벤트 루프는 이벤트가 들어온 이벤트 열이 비워질 때까지 이벤트 처리를 반복한다. 이벤트가 없으면 다음 이벤트를 기다리며 딴 일 한다.

요약 : dart 단일 쓰레드 단일 이벤트 루프(대부분의 상황에서)

 

 

 

 

 

 

Future

dart에서 비동기처리를 위한 API

닫힌 선물상자 -> 열었을 때 data나 error가 발생한다.

future은 위와 같은 세가지 상태를 가진다. 이 세가지 패턴을 처리한다.

RaisedButton(
     onPressed: () {
       final myFuture = http.get('https://my.imgae.url');
          myFuture.then((resp) {
       		setImage(resp);
        });
     },
    child: Text('Click me!'),
));

위와 같은 버튼을 눌렀을때 이미지를 http를 통해 받아오는 상황을 생각해보자.

사용자가 탭을 누르면 이벤트 루프가 탭을 받고 탭 핸들러가 호출 된다. 그럼 http라이브러리를 통해 future을 받는다. 그리고 future의 상자가 열릴 때 실행될 콜백을 myFuture.then을 통해 등록한다.

만약 future의 값이 생긴다면 콜백이 실행된다. future의 값이 http를 통해 등록되기 전까지 이벤트루프는 그냥 다른 할일 한다. 

 

future를 활용한 futurebuilder도 유용하게 쓸 수 있다.

만약 버튼을 눌렀을때 이미지를 받아오는 경우 위와 같이 future을 생성하고 statefulwidget으로 완료시 setstate를 하는 방법등으로 구현해도 되지만 그냥 

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return FutureBuilder<String>(
        future: _fetchNetworkData(),
        builder: (context, snapshot) {
          if (snapshot.hasError) {
            return Text('there is an error');
          } else if (snapshot.hasData) {
            return Text('there is an data');
          } else {
            return Text('No Value Yet');
          }
        });
  }
}

futurebuilder을 사용하면 future가 완료되었을시에 자동으로 builder가 실행된다.

snapshot에는 future의 상태가 담기는데 이 snapshot을 활용해서 예외처리나 완료시 할 일을 등록할 수 있다.

 

Stream

future Iterator 

마치 방송 stream처럼 순차대로 정보가 오는상황에도 처리할 수 있음

final myStream = NumberCreator().stream;

final subscription = myStream.listen(
	(data){}
	onEroor:
	cancleOnError:
	onDone:
);

요것도 streambuilder 지원해서 stream 변경때마다 새로운 위젯 만듬.

StreamBuilder<String>(
  stream: NumberCreator().stream
  .map((i) => 'String $i' ),
builder: (context, snapshot){
  //처리
})

 

async await

동기화를 위한 편한방법

예제로 확인해보자

 

1. future API 사용

Future<ProcessedData> createData(){
  return _loadFromDisk().then((id)
    {return _fetchNetworkData(id);
    }).then((data){
      return ProcessedData(data);
    });
}

 

 

 

 

2. async await 사용

Future<int> _loadFromDisk(){}

Future<String> _fetchNetworkData(int id){}

processedData(data)


ProcessedData createData() async {
 try{
    final id = await _loadFromDisk();
    final data = await _fetchNetworkData(id);
    return processedData(data);
 } on HttpException catch (err) {
 	print('error');
    return ProcessedData.empty();
 }	finally {
	print('All done!') ;
 }
}

방식은 똑같음 처음 id에 future주고 await이기 때문에 disk나 network에서 data 줄 때까지 기다린다?

 

 

음 아직 모르겠지만 async await가 보기에도 에러처리 하기에도 편해보임.

 

'study > flutter' 카테고리의 다른 글

Flutter- StateManagement, Provder  (0) 2020.07.26