مدیریت state در فلاتر: setState، Provider، Riverpod یا Bloc؟

انتخاب راه‌حل مدیریت state یکی از اولین سؤال‌های هر برنامه‌نویس فلاتر است. این مقاله فرق setState، Provider، Riverpod و Bloc را با مثال کد توضیح می‌دهد و می‌گوید در چه پروژه‌ای کدام را انتخاب کنید.

۳ دقیقه مطالعه۱ بازدید
مدیریت state در فلاتر: setState، Provider، Riverpod یا Bloc؟

«State» یعنی داده‌ای که رابط کاربری بر اساس آن ساخته می‌شود و با گذر زمان عوض می‌شود: شمارنده‌ی سبد خرید، کاربر واردشده، نتیجه‌ی یک جستجو. سؤال اصلی این است: این داده کجا نگه داشته شود و چطور رابط با تغییرش به‌روز شود؟

#۱. setState، ساده‌ترین راه

برای state محلی یک ویجت (مثل باز یا بسته بودن یک پنل) کافی است:

class CounterPage extends StatefulWidget {
  const CounterPage({super.key});
  @override
  State<CounterPage> createState() => _CounterPageState();
}

class _CounterPageState extends State<CounterPage> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () => setState(() => count++),
      child: Text('$count'),
    );
  }
}

مشکل وقتی شروع می‌شود که چند صفحه به یک داده نیاز دارند. تا آنجا که ممکن است state را به بالا ببرید، ولی بعد از یک حدی بدون ابزار مناسب پیچیده می‌شود.

#۲. Provider

لایه‌ی ساده‌ای روی InheritedWidget است. یک کلاس ChangeNotifier می‌سازید و بالای درخت ویجت‌ها قرار می‌دهید:

class CartModel extends ChangeNotifier {
  final List<String> items = [];
  void add(String item) {
    items.add(item);
    notifyListeners();
  }
}

// near the root
ChangeNotifierProvider(create: (_) => CartModel(), child: const MyApp());

// in any widget below
final cart = context.watch<CartModel>();

یادگیری‌اش آسان است و برای پروژه‌های کوچک تا متوسط عالی کار می‌کند.

#۳. Riverpod

نسل تکامل‌یافته‌ی Provider: وابسته به BuildContext نیست، تست‌پذیری بهتری دارد و کامپایل‌تایم امن‌تر است:

final counterProvider = NotifierProvider<Counter, int>(Counter.new);

class Counter extends Notifier<int> {
  @override
  int build() => 0;
  void increment() => state++;
}

// in a ConsumerWidget
final count = ref.watch(counterProvider);
ref.read(counterProvider.notifier).increment();

برای کار با داده‌های ناهمگام (درخواست شبکه) هم ابزارهای آماده دارد.

#۴. Bloc

الگوی «رویداد ← حالت». هر عملیات یک رویداد است و خروجی یک state جدید. کدنویسی بیشتری می‌خواهد ولی نظم و قابل‌پیش‌بینی‌بودنش برای تیم‌های بزرگ و اپ‌های پیچیده ارزشمند است.

#کدام را انتخاب کنم؟

  • پروژه‌ی کوچک یا یادگیری: setState و ValueNotifier.
  • پروژه‌ی متوسط و تک‌نفره: Provider یا Riverpod.
  • پروژه‌ی بزرگ و تیمی با جریان‌های پیچیده: Riverpod یا Bloc.

#سه توصیه‌ی عملی

  • state را کوچک و نزدیک به جایی که استفاده می‌شود نگه دارید.
  • منطق کسب‌وکار را از ویجت‌ها جدا کنید تا بشود جدا تستش کرد.
  • یک ابزار انتخاب کنید و در کل پروژه ثابت بمانید؛ مخلوط‌کردن چند راه‌حل بدتر از انتخاب یک راه‌حل متوسط است.

بهترین ابزار مدیریت state ابزاری است که تیم شما خوب بلد است.

فلاتر را حرفه‌ای و پروژه‌محور یاد بگیر

دوره‌ی VIP فست فلاتر از صفر تا انتشار اپلیکیشن، با پشتیبانی مستقیم مدرس.

مشاهده‌ی دوره‌ی VIP