riverpod의 dispose와 initialize

su.log·2023년 12월 15일
0

일반적으로 AutoDisposeProvider는 생성된 공급자가 더 이상 필요하지 않을 때 자동으로 삭제됩니다.
그러나 addListener 등을 사용했을때 dispose되는 시점에 수동으로 dispose를 해줘야 할 때가 있습니다.
그때는 ref.onDispose를 통해서 provider내에서 사용했던 Listener 등등을 dispose시켜 줍니다.

ref.onDispose는 아래와 같이 실행해 주면 됩니다.

FutureOr<VideoPlayerModel?> build() async {
    await initialize(
      autoPlay: false,
    );
    final data = VideoPlayerModel(
      playerController: controller!,
      isOverlayWidgetOn: false,
      fullScreen: false,
      play: false,
      currentVideoPosition: Duration.zero,
    );
   	state = data;
    /// build 단에서 ref.onDispose를 실행시켜 준다.
    ref.onDispose(dispose);
    return data;
  }

작업을 하면서 문제가 총 두가지 있었습니다.

첫번째 문제는 dispose 자체가 불리지 않는 문제였습니다.
그 이유는 provider를 컴포넌트 별로 세개로 나눠 사용했는데 두개의 provider를 각각의 메소드 내에서 필요 시마다 참조하는 식으로 사용을 했습니다. 이렇게 양방향으로 참조하다보니 계속 사용 을 하는 것으로 인식을 하여 dispose가 되는 시점을 판단하지 못한다고 추측 되었습니다.
서로 참조하는 provider를 하나로 사용하도록 구조를 변경 하였고 dispose가 잘 호출되는 것을 확인할 수 있었습니다.

두번째 문제는 dispose가 된 후에 다시 Initialize 되지 않는 문제였습니다.
AutoDisposeNotifierProvider를 사용했을 때,
dispose가 된 후 해당 페이지에 들어가면 인스턴스를 새로 생성해야 하는데 dispose가 된 페이지라는 error message와 함께 빨간 화면을 발생 시켰습니다.
dispose가 된 후에 build가 재호출 되지 않아 생기는 문제였습니다.
안되는 이유는 생각보다 단순 했는데 해당 provider를 소비하는 UI 클래스에서 dispose시에 ref.read를 통해 dispose가 이미 되어버린 provider를 참조하고 있었기 때문입니다.

 @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    //여기가 문제
    ref.read(videoPlayerProvider.notifier).wakelock(false);
    super.dispose();
  }

위의 코드를 지워주니 initialize도 잘 동작 하는 것을 확인 할 수 있었습니다.

0개의 댓글