본문으로 건너뛰기

.autoDispose

통상적으로 프로바이더를 사용할때, 프로바이더를 더이상 사용하지 않는다면 시스템 메모리상에서 해제(destroy)하고 싶은 경우가 있습니다.

destroy하고 싶은 경우는 다양한 이유가 있지만 아래의 경우를 생각해볼 수 있습니다.

  • 파이어베이스(Firebase)를 사용할떄 불필요한 코스트 발생을 피하기 위해 연결을 끊는 경우
  • 사용자가 화면상에서 떠나고 재진입했을때 상태를 초기화 해줘야 하는 경우

위의 경우등을 대응할 수 있도록 프로바이더는 빌트인으로 .autoDispose 수식어를 지원합니다.

사용방법

Riverpod에 더이상 사용하지 않는 프로바이더의 상태를 소멸(destroy)하기위해 .autoDispose 수식어를 프로바이더에 붙이기만 하면 됩니다.

final userProvider = StreamProvider.autoDispose<User>((ref) {

});

이것으로 userProvider가 더 이상 사용되지 않을때 자동으로 해제 작업을 처리합니다.

제네릭 파라미터가 autoDispose전에 붙는게 아닌 autoDispose뒤에 붙는 것으로 알 수 있듯이 autoDispose는 a named constructor가 아닙니다.

노트

.autoDispose와 다른 수식어를 결합할 수 있습니다.

final userProvider = StreamProvider.autoDispose.family<User, String>((ref, id) {

});

ref.keepAlive

프로바이더에 autoDispose 수식어를 붙이면 ref객체에 keepAlive 메소드를 사용할 수 있습니다.

keepAlive 메소드를 실행하는 것으로, 프로바이더가 참조되지 않게 되었을 때에도 상태를 유지하도록 Riverpod 에 전할 수가 있습니다.

좀 더 이해를 돕기위해서 HTTP 요청이 완료되면 플레그를 true로 설정하는 예시 코드입니다.

final myProvider = FutureProvider.autoDispose((ref) async {
final response = await httpClient.get(...);
ref.keepAlive();
return response;
});

위의 방식을 사용하면, 만약에 요청이 실패하고 사용자가 화면상에서 떠나고 다시 들어온 경우 요청을 재 실행할 수 있도록 합니다. 그러나, 만약 요청이 성공적으로 처리된다면, 상태가 유지될 것입니다. 그리고 화면에 재 진입해도 새로운 요청을 위한 트리거링이 발생하지 않습니다.

사용예: 더 이상 프로바이더를 사용하지 않을 때, HTTP 요청 취소하기

autoDispose 수식어는 FutureProviderref.onDispose에 결합 할 수 있습니다. 프로바이더를 더 이상 사용하지 않을 때 쉽게 HTTP 요청을 취소할 수 있습니다.

이번 예시의 목표는 다음과 같습니다.

  • 사용자가 화면에 들어왔을 때 HTTP 요청을 시작합니다.
  • 만약 요청이 완료되기 전에 사용자가 화면을 떠났다면, HTTP을 취소합니다.
  • 만약 요청이 성공했다면, 화면을 떠나거나 재 진입했을때 새로운 요청을 시작하지 않습니다.

코드로 구현해 본다면 아래와 같습니다.

final myProvider = FutureProvider.autoDispose((ref) async {
// http 요청을 취소하기 위한 package:dio 객체
final cancelToken = CancelToken();
// 프로바이더가 해제(destroyed)될 때, http 요청을 취소합니다.
ref.onDispose(() => cancelToken.cancel());

// 데이터를 가져오고 취소하기 위한 `cancelToken`을 파라미터로 념겨줍니다.
final response = await dio.get('path', cancelToken: cancelToken);
// 만약 요청이 성곡적으로 완료되었다면, 현재 상태를 유지합니다.
ref.keepAlive();
return response;
});

'AutoDisposeProvider'인수 타입은 'AlwaysAliveProviderBase' 매개변수에 할당할 수 없습니다.

.autoDispose를 사용할 때, 아래와 같은 에러가 발생하면서 컴파일이 되지 않는 경우를 만나볼 수 있습니다.

The argument type 'AutoDisposeProvider' can't be assigned to the parameter type 'AlwaysAliveProviderBase'

걱정 하지 마세요! 이 에러는 자발적으로 발생하는 오류입니다. 버그가 발생할 가능성이 높기 때문에 발생하는 오류입니다.

.autoDispose의 수식어를 붙이지 않은 프로바이더에서 .autoDispose 수식어를 사용한 프로바이더를 사용할 경우 발생할 수 있습니다.

final firstProvider = Provider.autoDispose((ref) => 0);

final secondProvider = Provider((ref) {
// 'AutoDisposeProvider<int>'인자 값을
// 'AlwaysAliveProviderBase<Object, Null>' 파라미터 타입으로 할당할 수 없습니다.
ref.watch(firstProvider);
});

위의 코드의 경우 firstProvider가 절대 disposed 처리 않음으로 사용상 바람직하지 않습니다.

이를 수정하기 위해 secondProvider.autoDispose를 추가할 필요가 있습니다.

final firstProvider = Provider.autoDispose((ref) => 0);

final secondProvider = Provider.autoDispose((ref) {
ref.watch(firstProvider);
});