Sparround

Tipik səhvlər və xəta mesajları

Provider ilə bağlı xətaların böyük hissəsi eyni üç kökdən gəlir: səhv `context`, səhv ömür, səhv oxunuş növü. Xəta mesajını tanımaq müsahibədə də praktikada da vaxt qazandırır.

XətaSəbəbHəll
`ProviderNotFoundException` — "Could not find the correct Provider<T> above this widget"Oxunuş elə `context`-lə aparılır ki, provider ondan yuxarıda deyil (məsələn provider-in yaradıldığı widget-in öz `context`-i, ya da dialoq/route kontekstindən kənar)Provider-i daha yuxarı qaldırmaq, ya da alt ağac üçün `Builder`/ayrı widget ilə yeni `context` almaq
"A ChangeNotifier was used after being disposed"Mövcud obyekt `create`-ə verilib və provider onu sökmüş; ya da async əməliyyat notifier söküldükdən sonra qayıdıb `notifyListeners()` çağırır`.value` istifadə etmək; async-dan sonra obyektin hələ yaşadığını yoxlamaq
"setState() or markNeedsBuild() called during build"`build` gedişində `notifyListeners()` çağırılır — məsələn `build` içindən metod işə salınırYükləməni `initState`/`didChangeDependencies`-ə köçürmək, ya da bir frame gecikdirmək
UI heç yenilənmir`build`-də `read` istifadə olunub; ya `notifyListeners()` çağırılmayıb; ya `select` mutable dəyər qaytarır`watch`/`Consumer`-ə keçmək; immutable dəyər seçmək

Provider sənədində faydalı bir detal var: tipi nullable yazsanız (context.watch<Model?>()), provider ağacda yoxdursa exception atılmır, null qaytarılır. Bu, opsional provider-lər üçün nəzərdə tutulub — lakin onu ProviderNotFoundException-ı gizlətmək üçün istifadə etmək bug-ı səssiz edir. Müsahibədə bu nüansı bilmək diqqət göstərir.

dart
// ❌ showDialog-un builder-i başqa (Navigator-un overlay) context-i alır;
// provider bu context-dən yuxarıda olmaya bilər → ProviderNotFoundException.
void _confirm(BuildContext context) {
  showDialog(
    context: context,
    builder: (dialogContext) => AlertDialog(
      content: Text(dialogContext.watch<CartModel>().summary),
    ),
  );
}

// ✅ Variant 1: dəyəri dialoq açılmadan əvvəl oxumaq.
void _confirm(BuildContext context) {
  final summary = context.read<CartModel>().summary;
  showDialog(
    context: context,
    builder: (_) => AlertDialog(content: Text(summary)),
  );
}

// ✅ Variant 2: mövcud modeli dialoq ağacına .value ilə ötürmək.
void _confirm(BuildContext context) {
  final cart = context.read<CartModel>();
  showDialog(
    context: context,
    builder: (_) => ChangeNotifierProvider.value(
      value: cart,
      child: const CartDialog(),
    ),
  );
}

Ən çox rastlanan hal: dialoqda provider tapılmır.

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