[Flutter] Future Builder를 활용해 Display하기

2023. 3. 17. 01:20Developers 공간 [Shorts]/Frontend

728x90
반응형
<분류>
A. 수단
- OS/Platform/Tool : Linux, Kubernetes(k8s), Docker, AWS
- Package Manager : node.js, yarn, brew, 
- Compiler/Transpillar : React, Nvcc, gcc/g++, Babel, Flutter

- Module Bundler  : React, Webpack, Parcel

B. 언어
- C/C++, python, Javacsript, Typescript, Go-Lang, CUDA, Dart, HTML/CSS

C. 라이브러리 및 프레임워크 및 SDK
- OpenCV, OpenCL, FastAPI, PyTorch, Tensorflow, Nsight

 


1. What? (현상)

카메라 패키지를 사용하는 위젯에서 초기화하는 과정에 async한 작업들이 들어가는데, async하게 초기화되는 변수에 따라서 다르게 렌더링하는 것이 잘 되지 않았습니다.

 

stateful 위젯의 경우는 아래처럼 initState()에서 .then()을 활용해 late 변수를 초기화하고 ,

late CameraController camController;
@override
void initState() {
super.initState();
camController = CameraController(widget.camera, ResolutionPreset.max);
camController.initialize().then((_) {
if (!mounted) {
return;
}
setState(() {});
}).catchError((Object e) {
if (e is CameraException) {
switch (e.code) {
case 'CameraAccessDenied':
// Handle access errors here.
break;
default:
// Handle other errors here.
break;
}
}
});
}

future 값이 초기화 되었는지를 확인해 아래와 같이 렌더링 하는 방식을 활용하면 됩니다.

if (!camController.value.isInitialized) {
return Container(
width: MediaQuery.of(context).size.width,
child: CircularProgressIndicator(
semanticsLabel: 'Circular progress indicator',
)
);
}
return LayoutBuilder(
builder: (context, constraints) {
return SizedBox(
width: constraints.maxWidth,
height: constraints.maxHeight,
child: CameraPreview(camController),
);
},
);

근데 초기화가 잘되었는데도 불구하고, 가끔가다가 초기화된 변수의 상태를 반영해 렌더링하는 것이 잘 되지 않아 안정적으로 구현하고 싶습니다.


2. Why? (원인)

  • 처음엔 제가 사용하고 있는 ChangeNotifier 클래스에서 notifyListeners()를 하지 않아 생긴 문제인줄 알았지만, 해주어도 현상이 변하지 않습니다.
  • async하게 변경되는 camController.value.isInitialized 값을 반영해 렌더링해야 하는데, 이것이 잘되지 않아서 그렇습니다.

3. How? (해결책)

  • FutureBuilder를 활용해 display하면 더 안정적으로 구현할 수 있습니다.
  • 아래처럼 Future를 저장해두고(_initializeControllerFuture)
late CameraController camController;
Future<void>? _initializeControllerFuture;
@override
void initState() {
super.initState();
camController = CameraController(
widget.camera,
ResolutionPreset.medium,
);
_initializeControllerFuture = camController.initialize();
}
  • FutureBuilder()를 활용해 해당 Future object가 완성이 됐을 때와 아닐때를 구분해 렌더링하도록 구현합니다.
FutureBuilder<void>(
future: _initializeControllerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return CameraPreview(_controller);
} else {
return Center(child: CircularProgressIndicator());
}
},
)

https://flutter-ko.dev/docs/cookbook/plugins/picture-using-camera

 

728x90
반응형