Provider: این چیست، مدیر وضعیت برنامه‌های Flutter

نویسنده: IT Sectr منتشر شده: 2026-02-19 زمان مطالعه: 7 دقیقه

Provider — بسته مدیریت وضعیت برای Flutter، توسط Rémi Rousselet در سال 2019 به عنوان یک لایه بروی InheritedWidget ساخته شده است. Provider مسئله انتقال داده‌ها به پایین درخت ویجت‌ها بدون props drilling را حل می‌کند: هر ویجتی از طریق context.read<T>() یا context.watch<T>() به وضعیت دسترسی پیدا می‌کند. بر اساس pub.dev، Provider محبوب‌ترین مدیر وضعیت Flutter با بیش از 25 هزار لایک است.

نکات کلیدی

  • ChangeNotifier — کلاسی با notifyListeners برای اطلاع مشترکان از تغییرات
  • Consumer — ویجتی که با تغییر ChangeNotifier بازسازی می‌شود
  • MultiProvider — ترکیب چند Provider بدون تودرتونگی
  • ProxyProvider — Providerی که به Provider دیگری وابسته است
  • context.read / context.watch — روش‌های خواندن وضعیت بدون و با اشتراک

Provider چیست؟

Provider — بسته‌ای برای مدیریت وضعیت و وارد کردن وابستگی‌ها در Flutter، ساخته شده بر روی InheritedWidget. Provider یک شیئ‌ (وضعیت، سرویس، مخزن) را در درخت ویجت‌ها در دسترس قرار می‌دهد و با تغییر داده‌ها به طور خودکار UI را بازسازی می‌کند. به عنوان مثال، شما می‌توانید یک شیئ‌ را در هر جایی بدون ارسال آن از طریق سازنده دسترسی پیدا کنید.

Provider — روش به صورت رسمی توصیه شده توسط Google برای مدیریت وضعیت در Flutter (Flutter Team، 2019-2023). این بسته بخشی از Flutter Ecosystem است و توسط تیم Flutter پشتیبانی می‌شود. در زمان انتشار، Provider به عنوان جایگزینی برای متغیرهای سراسری و InheritedWidget پیشنهاد شد. بر اساس Flutter Community Survey 2025، Provider در 72% برنامه‌های Flutter استفاده می‌شود.

ChangeNotifier و notifyListeners

ChangeNotifier — کلاس داخلی Flutter است که الگوی Listener را پیاده‌سازی می‌کند. ChangeNotifier از طریق فراخوانی notifyListeners() مشترکان را از تغییر مطلع می‌کند. در زمینه Provider، ChangeNotifier کلاس اصلی برای وضعیت است: کلاسی از ChangeNotifier مشتق می‌شود که با صدــــ و روش‌هایی که پس از تغییر داده‌ها notifyListeners() را فراخوان می‌کنند، ایجاد می‌کند.

Dart
class CounterProvider extends ChangeNotifier {
  int _count = 0;
  int get count => _count;

  void increment() {
    _count++;
    notifyListeners();
  }

  void reset() {
    _count = 0;
    notifyListeners();
  }
}

قوانین notifyListeners: پس از تغییر کامل داده‌ها فراخوان شود — نه در وسط روش، بلکه در پایان. اگر روش چندین تغییر انجام می‌دهد، notifyListeners() را یک بار پس از تمامی تغییرات فراخوان کنید، نه پس از هر کدام.

جایگزین‌های ChangeNotifier: ValueNotifier — برای یک مقدار تک (مناسب برای نوع‌های ابتدایی)، StateNotifier — از بسته state_notifier (به ندرت به تنهایی استفاده می‌شود).

Consumer و context.watch

Consumer — ویجتی است که در ChangeNotifier مشترک می‌شود و با هر فراخوانی notifyListeners() بازسازی می‌شود. Consumer یک تابع builder با سه پارامتر می‌پذیرد: context، model، child. Child — ویجتی است که به مدل وابسته نیست و Consumer آن را بازسازی نمی‌کند. این یک بهینه‌سازی است: اگر درون Consumer یک ویجت استاتیک (آیکون، متن بدون داده) وجود داشته باشد، آن از طریق child ارسال می‌شود و مجدداً ایجاد نمی‌شود.

Dart
Consumer<CounterProvider>(
  builder: (context, provider, child) => Column(
    children: [
      child!, // بازسازی نمی‌شود
      Text('${provider.count}'),
      ElevatedButton(
        onPressed: () => provider.increment(),
        child: Icon(Icons.add),
      ),
    ],
  ),
  child: Text('شمارنده:'),
)

context.watch — روش افزونه BuildContext برای مشترک شدن در Provider. مدل را برمی‌گرداند و ویجت فعلی را در تغییرات آن مشترک می‌کند. context.read — دسترسی بدون مشترک شدن (برای گیرنده‌های onPressed، initState و dispose). context.select — مشترک شدن در یک صدـ مشخص مدل بدون بازسازی در صورت تغییر سایر صدـها.

MultiProvider و ProxyProvider

MultiProvider — ویجتی برای ثبت چند Provider بدون تودرتونگی. به جای درختی با 5 سطح Provider → Provider → Provider، MultiProvider یک لیست از providerها را می‌پذیرد. هر Provider بعدی می‌تواند از قبلی‌ها از طریق سازنده استفاده کند. MultiProvider — روش استاندارد سازماندهی سطح ریشه برنامه است.

Dart
MultiProvider(
  providers: [
    ChangeNotifierProvider(create: (_) => CartProvider()),
    ChangeNotifierProvider(create: (_) => AuthProvider()),
    ProxyProvider<AuthProvider, OrderProvider>(
      update: (_, auth, __) => OrderProvider(auth.userId),
    ),
  ],
  child: MaterialApp(home: HomePage()),
)

ProxyProvider — Providerی که به Provider دیگری وابسته است. ProxyProvider مقادیر را از سایر providerها دریافت می‌کند و آنها را به شیئ‌ خود ارسال می‌کند. به عنوان مثال، OrderProvider به AuthProvider وابسته است. ChangeNotifierProxyProvider — نسخه ProxyProvider برای ChangeNotifier.

StreamProvider و FutureProvider: StreamProvider در یک جریان (Firebase، WebSocket) مشترک می‌شود و Consumer را در هر رویداد جدید به‌روز می‌کند. FutureProvider — برای مقداردهی اسینکرون: Future را اجرا می‌کند، بارگذاری را نشان می‌دهد، سپس نتیجه را به ویجت‌ها ارسال می‌کند.

آزمایش Provider

Provider آزمایش می‌شود با احاطه کردن ویجت در MultiProvider با مقادیر آزمایشی. برای آزمایش به API یا پایگاه داده واقعی نیاز نیست — Provider با یک شیئ‌ مقلد جایگزین می‌شود. بسته provider از ProviderScope برای جداسازی آزمایش‌ها استفاده می‌کند.

Dart
import 'package:flutter_test/flutter_test.dart';

void main() {
  testWidgets('Counter increments on button tap',
    (tester) async {
      await tester.pumpWidget(
        ChangeNotifierProvider(
          create: (_) => CounterProvider(),
          child: CounterScreen(),
        ),
      );
      await tester.tap(find.byKey(Key('increment')));
      await tester.pump();
      expect(find.text('1'), findsOneWidget);
    },
  );
}

MockProvider: برای آزمایش ویجت‌ها با Provider وابسته به API، یک زیرکلاس مقلد ایجاد کنید یا از mockito / mocktail استفاده کنید.

Provider: کارایی و محدودیت‌ها

کارایی Provider بر پایه InheritedWidget است: با تغییر Provider، تمامی ویجت‌هایی که از طریق context.watch یا Consumer مشترک شده‌اند، بازسازی می‌شوند. برای جلوگیری از بازسازی‌های ضروری، از context.select، Consumer با پارامتر child و const برای ویجت‌های استاتیک استفاده کنید.

روشاشتراکبازسازیکاربرد
context.watchمدل کاملهر تغییریویجت‌های ساده
Consumerمدل کاملهر تغییریبا بهینه‌سازی child
context.selectصدـ مشخصتنها با تغییر صدـمدل‌های پیچیده
context.readنداردهرگزگیرنده‌های رویداد

محدودیت‌ها: Provider از جداسازی منطق کسب و کار در سطح رویداد (مانند BLoC) پشتیبانی نمی‌کند. برای سناریوهای پیچیده، Provider از BLoC و Riverpod عقب می‌ماند.

سوالات متداول

تفاوت Provider با BLoC چیست؟

Provider — لایه‌ای بر روی InheritedWidget برای وارد کردن وابستگی‌ها با ChangeNotifier. BLoC — الگوی معماری با Event + Stream برای جداسازی منطق. Provider یادگیری آسان‌تری دارد، BLoC کد را ساختارمندتر می‌کند.

ChangeNotifierProvider چیست؟

ChangeNotifierProvider — نوعی Provider برای نمونه‌های ChangeNotifier. شیئ‌ را از طریق create ایجاد می‌کند، آن را در دسترس نسل‌ها قرار می‌دهد و Consumer را با فراخوانی notifyListeners بازسازی می‌کند.

چگونه از بازسازی‌های ضروری با Provider جلوگیری کنیم؟

از context.select به جای context.watch استفاده کنید — ویجت تنها با تغییر صدـ انتخابی بازسازی می‌شود. ChangeNotifierهای بزرگ را به چند کوچک تقسیم کنید. از Consumer child برای بخش‌های استاتیک استفاده کنید.

آیا می‌توان Provider را بدون ChangeNotifier استفاده کرد؟

بله. Provider (بدون ChangeNotifier) — برای وارد کردن شیئ‌های تغییرناپذیر (مخزن، مشتری API، پیکربندی). ValueListenableProvider — برای ValueNotifier. StreamProvider — برای جریان. FutureProvider — برای Future. ProxyProvider — برای Providerهای وابسته به دیگری.

ProviderNotFoundException چیست؟

ProviderNotFoundException — استثنای زمان اجرایی که در صورت تلاش برای دستیابی به Providerی که بالاتر در درخت ویجت‌ها اعلام نشده است، رخ می‌دهد. راه‌حل: Provider را بالاتر در درخت قرار دهید یا از MultiProvider در سطح MaterialApp استفاده کنید.

خلاصه

  • Provider — لایه‌ای بر روی InheritedWidget برای مدیریت وضعیت و DI در Flutter
  • ChangeNotifier — کلاسی با notifyListeners برای به‌روزرسانی واکنشی UI
  • Consumer و context.watch — اشتراک در تغییرات با بازسازی خودکار
  • MultiProvider — ترکیب providerها بدون تودرتونگی درخت
  • ProxyProvider — زنجیره وابستگی بین Providerها
  • context.select — اشتراک نقطه‌ای در صدـ مشخص مدل
  • StreamProvider و FutureProvider — پشتیبانی داخلی از داده‌های واکنشی و اسینکرون

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید