Sparround

AsyncValue: loading, error, data

AsyncValue<T> async state-in üç vəziyyətini bir tipdə birləşdirir: AsyncLoading, AsyncError, AsyncData. Bunun praktik mənası — isLoading, error, data sahələrini əl ilə saxlamaq və onların mümkün olmayan kombinasiyalarını (məsələn eyni vaxtda loading error) idarə etmək ehtiyacı aradan qalxır.

Riverpod 3-də AsyncValue sealed tipə çevrildi. Bu, Dart 3-ün pattern matching-i ilə birlikdə işləyir: switch bütün halları əhatə etdiyini kompilyator səviyyəsində yoxlayır. Həmçinin valueOrNull value adına dəyişdirildi.

dart
// 1) Pattern matching (rəsmi sənəddəki üslub):
final activity = ref.watch(activityProvider);

return switch (activity) {
  AsyncValue(:final value?) => Text(value.title),
  AsyncValue(:final error?) => Text('Xəta: $error'),
  _ => const CircularProgressIndicator(),
};

// 2) when — daha tanış forma:
return activity.when(
  data: (value) => Text(value.title),
  error: (error, stackTrace) => Text('Xəta: $error'),
  loading: () => const CircularProgressIndicator(),
);

// 3) Pull-to-refresh: refresh(provider.future) indikator üçün Future qaytarır.
RefreshIndicator(
  onRefresh: () => ref.refresh(activityProvider.future),
  child: ListView(children: [/* ... */]),
);

Rəsmi sənəddəki pattern matching üslubu və `when` alternativi.

VəziyyətNə göstərməkTipik səhv
İlk yükləmə (`AsyncLoading`, dəyər yoxdur)Skeleton və ya spinnerBoş ekran göstərmək
Yenidən yükləmə (dəyər var, `isLoading` true)Köhnə məzmun + kiçik indikatorSpinner göstərib məzmunu itirmək — ekran "tullanır"
Xəta, dəyər yoxdurXəta mesajı + "Yenidən yoxla" düyməsiSonsuz spinner qoymaq
Xəta, köhnə dəyər varKöhnə məzmun + xəbərdarlıq banner/SnackBarBütün ekranı xəta ilə əvəz etmək

Riverpod 3-ün avtomatik retry-ı. Sənədə görə provider hesablanarkən exception baş verdikdə avtomatik təkrar cəhd edilir — 10 dəfəyə qədər, 200 ms-dən 6.4 saniyəyə qədər eksponensial gecikmə ilə. Bununla belə, Error tipləri (bərpa olunmayan proqram səhvləri) və ProviderException təkrarlanmır. Davranış provider səviyyəsində, ProviderScope-da və ya ProviderContainer-də retry parametri ilə tənzimlənir; retry: (retryCount, error) => null isə onu tamamilə söndürür.

Async state ilə işləyərkən müsahibədə dəyər verən üç detal:

  • `AsyncValue.guard`try/catch yazmaq yerinə xətanı avtomatik AsyncError-a çevirir: state = await AsyncValue.guard(() => repo.save(todo));
  • `provider.future` — async provider-in nəticəsini Future kimi almağa imkan verir; testdə await container.read(provider.future), UI-da RefreshIndicator ilə istifadə olunur.
  • Optimistik yenilənmə — dəyişikliyi dərhal state-ə yazıb, sonra serverə göndərmək; xəta olarsa köhnə state-i geri qaytarmaq. İstifadəçi üçün ən sürətli görünən yanaşma, lakin geri qaytarma məntiqi mütləq yazılmalıdır.

📚 Mənbələr və sənədlər