Sparround

Ref qaydaları: watch, read, listen, invalidate

Rəsmi sənəd Ref-i belə təsvir edir: provider-lərlə əlaqə saxlamağın əsas yolu — Flutter-in BuildContext-inə bənzər rol.

Dörd əsas metod və onların yeri:

  • `ref.watch` — deklarativ dinləmə. Sənəd birbaşa yazır: bu, provider-ləri dinləməyin ən çox yayılmış üsuludur və ilk seçiminiz olmalıdır. Yeri: widget-in build metodu və provider-in gövdəsi.
  • `ref.read` — abunə olmadan cari dəyəri oxumaq. Yeri: yalnız istifadəçi hərəkətləri — düymə basılışı kimi callback-lər.
  • `ref.listen` — dəyişikliyə yan effekt ilə cavab vermək: dialoq göstərmək, naviqasiya, log. build içində təhlükəsizdir; build-dən kənarda (initState) isə ref.listenManual istifadə olunur.
  • `ref.onDispose` — provider söküləndə təmizləmə (subscription, timer, controller).

State-i sıfırlamaq üçün: ref.invalidate(provider) state-i atır və növbəti oxunuşda yenidən hesablayır; ref.refresh(provider) isə sənədin ifadəsi ilə invalidate + read-in sintaktik şəkəridir.

Sənədin xüsusi xəbərdarlığı: `ref.read`-i `ref.watch`-dan yayınmaq üçün "optimizasiya" vasitəsi kimi istifadə etməyin — bu, kodunuzu daha kövrək edir. Bu, müsahibədə çox verilən "performans üçün read istifadə etmək olar?" sualının rəsmi cavabıdır: yox, çünki read dəyişikliyi görmür və UI səssizcə köhnə dəyərlə qalır.

dart
class TodoPage extends ConsumerWidget {
  const TodoPage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // watch: deklarativ oxunuş, dəyişiklikdə rebuild.
    final todos = ref.watch(todosProvider);

    // listen: yan effekt — build içində təhlükəsizdir.
    ref.listen(todosProvider, (previous, next) {
      if (next.hasError) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('Yükləmə alınmadı')),
        );
      }
    });

    return Scaffold(
      body: switch (todos) {
        AsyncValue(:final value?) => TodoList(items: value),
        AsyncValue(:final error?) => ErrorView(message: '$error'),
        _ => const Center(child: CircularProgressIndicator()),
      },
      floatingActionButton: FloatingActionButton(
        // read: istifadəçi hərəkəti, abunəlik lazım deyil.
        onPressed: () => ref.read(todosProvider.notifier).add('Yeni tapşırıq'),
        child: const Icon(Icons.add),
      ),
    );
  }
}

// Provider daxilində: watch → asılılıq, onDispose → təmizləmə.
final chatProvider = StreamProvider<List<Message>>((ref) {
  final socket = ref.watch(socketProvider);
  final controller = socket.subscribe('chat');
  ref.onDispose(controller.close);
  return controller.stream;
});

Hər metod öz yerində.

MetodAbunəlikİcazəli yerTipik istifadə
`ref.watch`Var — dəyişiklikdə rebuild/yenidən hesablama`build`, provider gövdəsiDəyəri göstərmək, asılılıq qurmaq
`ref.read`YoxCallback-lər (`onPressed`, `onTap`)Notifier-in metodunu çağırmaq
`ref.listen`Var, lakin rebuild etmir`build` (kənarda `listenManual`)SnackBar, dialoq, naviqasiya, log
`ref.invalidate` / `ref.refresh`Callback-lər, notifier metodlarıYenidən yükləmə, pull-to-refresh

Rəsmi DO/DON'T qaydaları (müsahibədə birbaşa sitat gətirməyə dəyər):

  • Provider-i widget-dən inisiallaşdırmaqdan çəkinin — provider özünü özü inisiallaşdırmalıdır; əks halda race condition riski var.
  • Ephemeral state (form state, seçilmiş element, controller) üçün provider istifadə etməkdən çəkinin.
  • Provider-in inisiallaşdırılması zamanı yan effekt (məsələn form göndərmək) etməyin — provider oxunuş əməliyyatını təmsil edir.
  • ref.watch/read/listen-i statik məlum provider-lərlə işlədin — provider-i parametr kimi ötürmək statik analizi və lint-i işləməz edir.
  • Provider-ləri yalnız top-level final dəyişən kimi yaradın.

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