[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
반응형