Riverpod — Flutter کے لیے ایک مرتب شدہ حالت اور انحصار مینیجر، جسے Remi Rousselet نے 2021 میں Provider کے جانشین کے طور پر بنایا۔ Riverpod Provider کے بنیادی مسائل حل کرتا ہے: مرتب وقت کی جانچ کی کمی، BuildContext پر انحصار، اور ProviderNotFoundException کی پیچیدگی۔ pub.dev کے مطابق، پیکیج کو 5 ہزار سے زیادہ لائیکس ملے ہیں اور یہ نئے پروجیکٹس میں Provider کو فعال طور پر تبدیل کر رہا ہے۔
اہم نکات
Riverpod Flutter کے لیے ایک حالت کا انتظام اور انحصار انجیکشن لائبریری ہے جو فراہم کنندگان کی وضاحتوں کو محفوظ Dart کوڈ میں مرتب کرتی ہے۔ Provider کے برعکس، Riverpod فراہم کنندگان BuildContext سے منسلک نہیں ہوتے: وہ عالمی طور پر یا ProviderScope میں بنائے جاتے ہیں اور کہیں سے بھی قابل رسائی ہوتے ہیں۔ مرتب کنندہ تعمیر کے وقت اقسام، انحصار اور فراہم کنندہ گراف کی سالمیت کی جانچ کرتا ہے، جس سے ProviderNotFoundException جیسی رن ٹائم خرابیاں ختم ہو جاتی ہیں۔
Riverpod جانچ کے لیے override ماڈل استعمال کرتا ہے: ہر فراہم کنندہ کو ProviderScope.overrideWith کے ذریعے ذیلی کلاسز بنائے یا انٹرفیس mock کیے بغیر اوور رائیڈ کیا جا سکتا ہے۔ یہ جانچ کو الگ تھلگ بناتا ہے: ہر جانچ کو انحصار گراف کی اپنی کاپی ملتی ہے جو مکمل طور پر کنٹرول ہوتی ہے۔
Flutter Community Survey 2025 کے مطابق، Riverpod مقبولیت میں Provider اور BLoC کے بعد تیسرے نمبر پر ہے۔ تاہم، Riverpod سب سے تیزی سے بڑھنے والا پیکیج ہے: 2024 میں +120% تنصیبات۔ اہم وجوہات: مرتب وقتی تحفظ، کوئی ProviderNotFoundException نہیں، AsyncValue کے ذریعے بلٹ ان غیر متزامن معاونت۔
Riverpod 8 اقسام کے فراہم کنندگان فراہم کرتا ہے، ہر ایک مخصوص منظر نامے کے لیے: Provider (مستقل/خدمت)، StateProvider (بنیادی حالت)، StateNotifierProvider (StateNotifier کے ساتھ پیچیدہ منطق)، ChangeNotifierProvider (Provider سے منتقلی کے لیے)، FutureProvider (غیر متزامن ڈیٹا، ایک بار)، StreamProvider (رد عمل کا سلسلہ)، NotifierProvider (نیا API، Flutter 3.10+) اور AsyncNotifierProvider (غیر متزامن Notifier)۔
final counterProvider = StateNotifierProvider<CounterNotifier, int>((ref) {
return CounterNotifier();
});
class CounterNotifier extends StateNotifier<int> {
CounterNotifier() : super(0);
void increment() => state++;
void decrement() => state--;
}
class CounterScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider);
return Text('$count');
}
}ProviderRef — دوسرے فراہم کنندگان تک رسائی کے لیے ہر فراہم کنندہ کو دیا جانے والا آبجیکٹ۔ ref.watch — تبدیلیوں کی سبسکرپشن، ref.read — ایک بار پڑھنا، ref.invalidate — کیشے ری سیٹ۔ ProviderRef Provider کے BuildContext کو تبدیل کرتا ہے: کوئی بھی فراہم کنندہ ویجیٹ ٹری تک رسائی کے بغیر دوسرے فراہم کنندگان کو پڑھ سکتا ہے۔ یہ UI پرت کے باہر انحصار گراف بنانے کی اجازت دیتا ہے۔
ProviderScope — روٹ ویجیٹ، Riverpod کے کام کرنے کے لیے لازمی۔ ProviderScope تمام فراہم کنندگان کو ذخیرہ کرتا ہے، ان کی زندگی کے چکر کا انتظام کرتا ہے اور اقدار کو کیش کرتا ہے۔ ProviderScope کے بغیر ایپ ProviderNotFoundException کے ساتھ کریش ہو جائے گی۔ ProviderScope نیسٹڈ ہو سکتا ہے — نیسٹڈ اسکوپ والدین فراہم کنندگان کو اوور رائیڈ کرتا ہے، جو جانچ اور فیچر الگ تھلگ کرنے کے لیے استعمال ہوتا ہے۔
AsyncValue — غیر متزامن حالت کی نمائندگی کے لیے Riverpod کی مہربند کلاس۔ AsyncValue کی تین اقسام ہیں: AsyncData (کامیاب ڈیٹا)، AsyncError (خرابی)، AsyncLoading (لوڈ ہو رہا ہے)۔ loading/error/data کے درمیان دستی طور پر سوئچ کرنے کے بجائے، ہر FutureProvider یا StreamProvider خود بخود AsyncValue لوٹاتا ہے، اور ویجیٹ ref.watch کے ذریعے تینوں حالتوں کو سنبھالتا ہے۔
final userProvider = FutureProvider((ref) async {
final api = ref.watch(apiProvider);
return await api.fetchUser();
});
class UserScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final userAsync = ref.watch(userProvider);
return userAsync.when(
data: (user) => UserWidget(user),
error: (e, _) => ErrorWidget(e.toString()),
loading: () => CircularProgressIndicator(),
);
}
}AsyncValue.when — تینوں حالتوں کے پیٹرن میچنگ کے لیے ایک طریقہ۔ مرتب کنندہ جانچتا ہے کہ تینوں صورتوں کو سنبھالا گیا ہے — اگر آپ loading یا error بھول جاتے ہیں تو کوڈ مرتب نہیں ہوگا۔ AsyncValue.whenData — صرف ڈیٹا کے لیے (اگر loading/error کی ضرورت نہ ہو)۔ AsyncValue.guard — مستثنیات کو AsyncError میں تبدیل کرنے کے لیے try-catch پر لپیٹ۔ keepAlive — ایک جھنڈی جو فراہم کنندہ کیشے کو دائرہ کار سے باہر جانے پر تباہ ہونے سے روکتی ہے۔
کوڈ جنریشن — Riverpod 2.0+ کی ایک اہم خصوصیت۔ فنکشن پر @riverpod تشریح خود بخود صحیح قسم، ری فیکٹرنگ سپورٹ اور خودکار تکمیل کے ساتھ ایک فراہم کنندہ تیار کرتی ہے۔ کوڈ جنریشن riverpod_generator اور build_runner استعمال کرتی ہے۔ ڈویلپر ایک خالص فنکشن لکھتا ہے، اور باقی سب کچھ — اقسام، کلاسز، فیکٹری کنسٹرکٹر — خود بخود تیار ہو جاتے ہیں۔
@riverpod
String helloWorld(HelloWorldRef ref) {
return 'Hello World';
}
// تیار کردہ: final helloWorldProvider = Provider((ref) => 'Hello World');
@riverpod
class Counter extends _$Counter {
int build() => 0;
void increment() => state++;
}Notifier — کوڈ جنریشن کے ساتھ قابل تبدیلی حالت کے لیے نیا API۔ Notifier ایک کلاس ہے جس میں build() طریقہ اور حالت تبدیل کرنے کے طریقے ہیں۔ StateNotifier کے برعکس، Notifier کو علیحدہ حالت کی کلاس کی ضرورت نہیں ہوتی اور getter/setter کے ذریعے state تک براہ راست رسائی فراہم کرتا ہے۔ Riverpod @riverpod سے تشریح شدہ ہر Notifier کلاس کے لیے خود بخود NotifierProvider تیار کرتا ہے۔
build_runner: کوڈ جنریشن dart run build_runner build کمانڈ سے چلائی جاتی ہے۔ تیار کردہ فائلوں کا لاحقہ .g.dart ہوتا ہے اور وہ سورس کوڈ میں درآمد کی جاتی ہیں۔ جب تشریحات یا فراہم کنندہ کی اقسام تبدیل ہوتی ہیں، تو کوڈ جنریشن کو دوبارہ چلانے کی ضرورت ہوتی ہے۔ Riverpod 2.x تمام نئے پروجیکٹس کے لیے کوڈ جنریشن کی سفارش کرتا ہے — دستی فراہم کنندہ تخلیق متروک ہو رہی ہے۔
بنیادی فرق Riverpod اور Provider کے درمیان: BuildContext سے آزادی، مرتب وقتی تحفظ، بلٹ ان غیر متزامن معاونت، خودکار کیشنگ، اور override کے ذریعے جانچ۔ Provider کو حالت تک رسائی کے لیے BuildContext کی ضرورت ہوتی ہے (context.watch, context.read)، Riverpod WidgetRef اور عالمی طور پر اعلان کردہ فراہم کنندگان استعمال کرتا ہے۔
| خصوصیت | Provider | Riverpod |
|---|---|---|
| BuildContext انحصار | ہاں | نہیں |
| مرتب وقتی جانچ | نہیں | ہاں (@riverpod کے ذریعے) |
| ProviderNotFoundException | رن ٹائم | ناممکن |
| غیر متزامن | دستی | AsyncValue (بلٹ ان) |
| جانچ | Provider میں لپیٹ | ProviderScope.overrideWith |
| کیشنگ | نہیں | خودکار + keepAlive |
Provider سے منتقلی: Riverpod بغیر دوبارہ لکھے موجودہ ChangeNotifier استعمال کرنے کے لیے ChangeNotifierProvider.adaptive کو سپورٹ کرتا ہے۔ بتدریج منتقلی: پہلے نئی خصوصیات Riverpod میں لکھی جاتی ہیں، پھر پرانی Provider مثالیں ایک اڈاپٹر کے ذریعے Riverpod فراہم کنندگان سے تبدیل کر دی جاتی ہیں۔ دونوں پیکیج ایک پروجیکٹ میں ایک ساتھ رہ سکتے ہیں، جس سے ترقی کو روکے بغیر منتقلی ممکن ہوتی ہے۔
Riverpod کی جانچ ProviderScope.overrideWith پر مبنی ہے۔ ہر فراہم کنندہ بغیر mock یا DI کنٹینرز کے جانچ ProviderScope کے اندر اوور رائیڈ کیا جاتا ہے۔ ProviderContainer — Flutter کے بغیر جانچ کے لیے الگ تھلگ ماحول (خالص Dart)، ویجیٹ رینڈرنگ کے بغیر فراہم کنندگان کی جانچ کی اجازت دیتا ہے۔
import 'package:flutter_test/flutter_test.dart';
import 'package:riverpod/riverpod.dart';
void main() {
test('Counter increments correctly', () {
final container = ProviderContainer();
container.read(counterProvider.notifier).increment();
expect(container.read(counterProvider), 1);
});
testWidgets('UI updates on increment', (tester) async {
await tester.pumpWidget(
ProviderScope(
overrides: [counterProvider.overrideWithValue(5)],
child: CounterScreen(),
),
);
expect(find.text('5'), findsOneWidget);
});
}ProviderContainer — Flutter کے بغیر۔ ویجیٹ کے بغیر فراہم کنندگان کے یونٹ ٹیسٹ کے لیے ProviderContainer استعمال کریں۔ overrideWithValue — کسی مخصوص قدر سے فراہم کنندہ کو تبدیل کرنا۔ overrideWith — فراہم کنندہ فیکٹری سے تبدیل کرنا (خدمات کو mock کرنے کے لیے)۔ autodispose — جانچ میں تصدیق کریں کہ container.dispose() استعمال کرتے ہوئے فراہم کنندہ دائرہ کار سے باہر جانے پر تباہ ہو جاتا ہے۔
اکثر پوچھے گئے سوالات
Riverpod عالمی فراہم کنندگان، AsyncValue اور کوڈ جنریشن کے ساتھ ایک حالت کا انتظام کرنے والی لائبریری ہے۔ BLoC Event → Stream → State کے ساتھ ایک آرکیٹیکچرل پیٹرن ہے۔ Riverpod سیکھنا آسان ہے اور @riverpod تشریحات کے ذریعے بہتر DX فراہم کرتا ہے۔ BLoC BlocObserver کے ذریعے سخت کاروباری منطق کی علیحدگی اور ایونٹ ٹریسنگ فراہم کرتا ہے۔ انتخاب پروجیکٹ کے پیراڈائم پر منحصر ہے: Riverpod Provider کے قریب ہے، BLoC — رد عمل کے سلسلوں کے۔
Autodispose ایک میکانزم ہے جو خود بخود فراہم کنندہ کو تباہ کر دیتا ہے جب کوئی اس سبسکرائب نہ ہو۔ ڈیفالٹ کے طور پر، تمام Riverpod فراہم کنندگان autodispose کرتے ہیں: جب ویجیٹ درخت سے نکلتا ہے، فراہم کنندہ میموری سے ہٹا دیا جاتا ہے۔ keepAlive — ایک جھنڈی جو ان فراہم کنندگان کے لیے autodispose کو غیر فعال کرتی ہے جنہیں ہمیشہ زندہ رہنا چاہیے (API کلائنٹس، ریپوزٹریز، سیٹنگز)۔ یہ میموری لیک کو روکتا ہے — غیر استعمال شدہ فراہم کنندگان خود بخود تباہ ہو جاتے ہیں۔
ref.invalidate — ایک طریقہ جو زبردستی فراہم کنندہ کیشے کو ری سیٹ کرتا ہے۔ invalidate کے بعد، اگلی پڑھائی پر فراہم کنندہ دوبارہ بنایا جاتا ہے: FutureProvider غیر متزامن فنکشن دوبارہ چلاتا ہے، StreamProvider سلسلے کو دوبارہ سبسکرائب کرتا ہے۔ ڈیٹا ریفریش کو مجبور کرنے کے لیے invalidate استعمال کریں (پل ٹو ریفریش، صارف تبدیلی)۔ ref.refresh — invalidate + پڑھنے کا مجموعہ: ایک آپریشن میں ری سیٹ کرتا ہے اور فوری طور پر نئی قدر پڑھتا ہے۔
ہاں۔ Riverpod 1.x صرف کوڈ جنریشن کے بغیر کام کرتا ہے — فراہم کنندگان دستی طور پر Provider()، StateNotifierProvider()، FutureProvider() وغیرہ استعمال کرتے ہوئے بنائے جاتے ہیں۔ Riverpod 2.x دونوں طریقوں کو سپورٹ کرتا ہے۔ کوڈ جنریشن کے بغیر زیادہ بائلر پلیٹ ہے لیکن build_runner اور dart run build_runner build پر کوئی انحصار نہیں۔ چھوٹے پروجیکٹس (30 فراہم کنندگان تک) کے لیے دستی تخلیق جائز ہے؛ بڑے پروجیکٹس کے لیے کوڈ جنریشن لازمی ہے۔
Family — ایک فراہم کنندہ موڈیفائر جو بیرونی پیرامیٹر قبول کرتا ہے۔ مثال کے طور پر، userProvider(123) — ایک فراہم کنندہ جو ID 123 والے صارف کو لوڈ کرتا ہے۔ Family فراہم کنندگان ہر منفرد پیرامیٹر کے لیے علیحدہ طور پر نتیجہ کیش کرتے ہیں۔ آئٹمز کی فہرستوں کے لیے Family استعمال کریں جہاں ہر آئٹم ID کے ذریعے لوڈ ہوتا ہے۔ Family موڈیفائر تمام فراہم کنندہ اقسام کے لیے دستیاب ہے: Provider.family، FutureProvider.family، StreamProvider.family۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔