Sparround

Oxumaq: watch, read, select, Consumer

Provider-də dəyəri oxumağın dörd yolu var və aralarındaki fərq abunəlikrebuild sahəsi ilə ölçülür.

  • context.watch<T>() — dəyəri qaytarır və widget-i abunə edir. Dəyişiklikdə bütün `build` metodu yenidən işləyir. Yalnız build içində istifadə olunur.
  • context.read<T>() — abunəlik yaratmır. onPressed kimi callback-lərdə metod çağırmaq üçündür.
  • context.select<T, R>((T value) => ...) — yalnız seçilmiş hissəyə abunə edir: R dəyişməyibsə rebuild yoxdur.
  • Consumer<T> / Selector<T, R> — abunəliyi widget səviyyəsində məhdudlaşdırır: yalnız builder-in qaytardığı hissə yenilənir.

Provider.of<T>(context, listen: false)read-in köhnə, uzun yazılışıdır; listen: true isə watch-a bərabərdir.

MəqsədDüzgün alətTipik səhv
`build`-də dəyəri göstərmək`context.watch<T>()` və ya `Consumer<T>``read` istifadə etmək → UI yenilənmir
Düymə basılanda metod çağırmaq`context.read<T>().doIt()``watch` istifadə etmək → lazımsız abunəlik
Modelin yalnız bir sahəsini izləmək`context.select((T v) => v.field)` / `Selector`Bütün modeli `watch` etmək → hər dəyişiklikdə rebuild
`initState`-də ilkin dəyər almaq`context.read<T>()``watch` çağırmaq → framework qadağası

Rəsmi Flutter sənədinin birbaşa tövsiyəsi: `Consumer` widget-lərini ağacda mümkün qədər dərində yerləşdirin — kiçik bir detal dəyişdiyi üçün UI-ın böyük hissəsini yenidən qurmaq istəmirsiniz. Provider sənədi isə əksini xəbərdarlıq edir: read-i build metodunda dəyər oxumaq üçün istifadə etməyin, watch üçün isə initState yeri deyil.

dart
// ❌ Bütün ekran səbətin hər dəyişikliyində rebuild olunur.
@override
Widget build(BuildContext context) {
  final cart = context.watch<CartModel>();
  return Column(
    children: [
      const ExpensiveBanner(),
      HeavyProductGrid(items: allProducts),
      Text('Cəmi: ${cart.totalPrice}'),
    ],
  );
}

// ✅ Yalnız Text rebuild olunur; grid child kimi ötürülür.
@override
Widget build(BuildContext context) {
  return Column(
    children: [
      const ExpensiveBanner(),
      HeavyProductGrid(items: allProducts),
      Consumer<CartModel>(
        builder: (context, cart, child) => Text('Cəmi: ${cart.totalPrice}'),
      ),
    ],
  );
}

// ✅ Yalnız bir sahəyə abunəlik: səbətə element əlavə olunsa da,
// totalPrice dəyişməyibsə rebuild olunmur.
final total = context.select<CartModel, double>((c) => c.totalPrice);

`Consumer`-in `child` parametri: dəyişməyən ağır hissə bir dəfə qurulur.

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