사용자가 새로운 아이 패치를 추가하는 단계에서 주변 ble 기기들을 스캔할 때 이 위젯을 사용하게 되었다. ble 기기 스캔에는 flutter blue 라이브러리를 사용했는데, 이 때 timeout 설정을 통해 주변 기기를 4초 동안 스캔하도록 설정한 뒤 리스트(resultList)에 스캔 결과들을 차례대로 담았다. 아래는 ble 기기들을 스캔하는 함수이다.
Future<List<ScanResult>> scanPatch() async {
setState(() {
_resultList.clear();
});
await flutterBlue.startScan(timeout: const Duration(seconds: 4));
flutterBlut.scanResults.listen((results) {
for (ScanResult r in results) {
if (!_resultList.contains(r)) {
_resultList.add(r);
}
}
});
return _resultList;
}
이 함수가 실행되면 4초 동안의 스캔이 다 끝난 뒤 요소들이 담긴 리스트(_resultList)가 반환될텐데, 이 때 해당 리스트를 리스트뷰 형식으로 한 번에 화면에 띄워주고 싶었다. 여기서 FutureBuilder 위젯을 사용하여 이를 구현할 수 있었다. 이렇게!
FutureBuilder는 Future를 다루는 위젯이다. Future는 지금은 아직 사용할 수 없지만 미래에 있을 값을 나타내는 객체이다. 비동기 작업 처리에 사용된다.
그러면 FutureBuilder는 말 그대로 Future를 빌드하는 위젯인 것이다.
FutureBuilder로 Future의 현재 상태를 쉽게 파악하고, 데이터를 불러오는 동안 보여줄 것과 데이터가 다 불러와졌을 때 보여줄 것들을 따로 설정할 수 있다.
먼저 스캔 결과들이 담길 Future 객체를 선언한다.
(이 때 꼭 FutureBuilder 밖에서 선언해야 한다. FutureBuilder 안에서 선언할 경우 FutureBuilder의 상위 요소가 다시 구축될 때마다 데이터를 다시 가져오게 된다.)
late Future<List<ScanResult>> _scanPatch;
그리고 나의 경우, 스캔을 시작하는 textButton을 생성한 뒤 클릭할 때 기기 스캔 함수(scanPatch())가 실행되도록 해줬다.
FutureBuilder 는 다음과 같이 생성했다.
FutureBuilder 안의 future에 앞서 선언한 Future 객체인 _scanPatch 를 전달한다.
FutureBuilder의 snapshot의 connectionState를 통해 Future의 상태를 확인하고 이에 맞는 적절한 화면을 보여준다.
FutureBuilder(
future: _scanPatch,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Container(
ListView.spread(
itemBuilder: (BuildContext, index) {
return ListTile(
title: Text(_resultList[index].device.name)
);
}
)
);
} else if (snapshot.connectionState == ConnectionState.waiting) {
return LoadingIndicator();
} else return Container();
}
)
(위 코드는 실제 코드에서 css 요소들을 생략함)