AsyncValue vs AsyncData

topics 500-모바일개발 501 Flutter 504 Riverpod
types 이론 레퍼런스
tags #flutter #riverpod #asyncvalue
references github.com/rrousselGit/riverpod/discu... riverpod.dev/docs/concepts/reading

AsyncValue vs AsyncData

Riverpod에서 비동기 상태를 다루는 타입들의 차이다.

AsyncValue 구조

sealed class AsyncValue<T> {
  // 세 가지 하위 클래스
}

class AsyncData<T> extends AsyncValue<T> {
  final T value;
}

class AsyncLoading<T> extends AsyncValue<T> {}

class AsyncError<T> extends AsyncValue<T> {
  final Object error;
  final StackTrace stackTrace;
}

핵심 차이

  • AsyncValue: 로딩, 데이터, 에러 상태를 모두 포함하는 Sealed Class
  • AsyncData: AsyncValue의 하위 클래스로, 데이터가 있는 상태만 나타냄

사용 예시

when - 모든 상태 처리

final userState = ref.watch(userProvider);

userState.when(
  loading: () => CircularProgressIndicator(),
  error: (e, stack) => Text('Error: $e'),
  data: (user) => Text(user.name),
);

maybeWhen - 일부 상태만 처리

userState.maybeWhen(
  data: (user) => Text(user.name),
  orElse: () => CircularProgressIndicator(),
);

whenData - 데이터만 변환

final nameState = userState.whenData((user) => user.name);
// AsyncValue<User> → AsyncValue<String>

유용한 프로퍼티

// 현재 상태 확인
userState.isLoading   // 로딩 중인가
userState.hasError    // 에러인가
userState.hasValue    // 데이터가 있는가

// 값 접근
userState.value       // T? - null일 수 있음
userState.valueOrNull // T? - value와 동일
userState.requireValue // T - null이면 에러

AsyncValue.guard

try-catch 대신 사용하면 깔끔하다.

// 이전 방식
try {
  state = AsyncValue.data(await fetchUser());
} catch (e, stack) {
  state = AsyncValue.error(e, stack);
}

// AsyncValue.guard
state = await AsyncValue.guard(() => fetchUser());

이전 값 유지하기

로딩 중에도 이전 값을 보여주고 싶을 때.

final userState = ref.watch(userProvider);

// isLoading이면서 value가 있을 수 있음
if (userState.isLoading && userState.hasValue) {
  return Stack(
    children: [
      UserWidget(user: userState.value!),
      LoadingOverlay(),
    ],
  );
}