일반적으로 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도 잘 동작 하는 것을 확인 할 수 있었습니다.