StreamBuilder: یہ کیا ہے، کام کرنے کا اصول اور Flutter میں اطلاق

مصنف: IT Sectr اشاعت: 2026-07-03 مطالعے کا وقت: 8 منٹ

StreamBuilder ایک Flutter ویجیٹ ہے جو غیر متزامن اسٹریم سے نیا ڈیٹا موصول ہونے پر خود بخود انٹرفیس کو دوبارہ تعمیر کرتا ہے۔ FutureBuilder کے برعکس، جو ایک ہی نتیجے کے ساتھ کام کرتا ہے، StreamBuilder اسٹریم کی پوری زندگی کے دوران UI کی مسلسل اپ ڈیٹس کو سپورٹ کرتا ہے۔ سرکاری Flutter دستاویزات (2026) کے مطابق، StreamBuilder ریئل ٹائم ایپلیکیشنز میں استعمال ہوتا ہے: چیٹس، نیوز فیڈز، سینسر مانیٹرنگ اور مالیاتی ٹکرز۔ یہ ری ایکٹیو پروگرامنگ کا ایک اہم ذریعہ ہے، جہاں UI دستی setState کالز کے بغیر ڈیٹا کی حالت کی عکاسی کرتا ہے۔

اہم نکات

  • StreamBuilder — ایک ویجیٹ جو ری ایکٹیو UI رینڈرنگ کے لیے Stream اور ڈیٹا سنیپ شاٹ قبول کرتا ہے
  • سنیپ شاٹ میں connectionState، data اور error ہوتا ہے، جو اسٹریم کی موجودہ حالت کی وضاحت کرتا ہے
  • ConnectionState چار مراحل سے گزرتا ہے: none، waiting، active، done
  • AsyncSnapshot — ایک ناقابل تبدیلی آبجیکٹ جو ہر فریم پر ڈیٹا کی مستقل مزاجی کو یقینی بناتا ہے
  • StreamController اسٹریم کا انتظام کرتا ہے: ڈیٹا شامل کرتا ہے، غلطیوں کو ہینڈل کرتا ہے اور Stream کو بند کرتا ہے

StreamBuilder کیا ہے

StreamBuilder Flutter SDK پیکج کا ایک ویجیٹ ہے جو Stream کو سبسکرائب کرتا ہے اور ہر نئے اسٹریم ایونٹ پر اپنے چائلڈ عنصر کو دوبارہ تعمیر کرتا ہے۔ StreamBuilder ایک Stream آبجیکٹ قبول کرتا ہے اور اسٹریم سے موصول ہونے والے تازہ ترین سنیپ شاٹ کی بنیاد پر ایک ویجیٹ لوٹاتا ہے۔

Flutter فن تعمیر میں، StreamBuilder Builder ویجیٹس کے گروپ سے تعلق رکھتا ہے جو UI کی تعمیر کو ڈیٹا کی حالت سے الگ کرتا ہے۔ StatefulWidget کے برعکس، جہاں حالت تبدیل کرنے کے لیے واضح setState کال کی ضرورت ہوتی ہے، StreamBuilder غیر متزامن واقعات پر خود بخود ردعمل ظاہر کرتا ہے، کوڈ کو آسان بناتا ہے اور ہم آہنگی کی غلطیوں کے خطرے کو کم کرتا ہے۔

FutureBuilder کے برعکس، جو ایک ہی غیر متزامن قدر کو ہینڈل کرتا ہے، StreamBuilder مسلسل ڈیٹا اسٹریمز کے لیے ڈیزائن کیا گیا ہے۔ FutureBuilder پہلا نتیجہ حاصل کرنے کے بعد ختم ہو جاتا ہے، جبکہ StreamBuilder اسٹریم سنتا رہتا ہے اور ہر نئے ایونٹ پر UI کو اپ ڈیٹ کرتا ہے۔

StreamBuilder ان تمام منظرناموں میں استعمال ہوتا ہے جہاں ڈیٹا مسلسل آتا ہے: WebSocket کنکشنز، سینسر کال بیکس، Firebase اطلاعات، Bluetooth ایونٹ قطاریں، اور BLoC کے ذریعے ایپلیکیشن سٹیٹ براڈکاسٹنگ۔ GitHub پر Flutter پروجیکٹس کے تجزیے (2025) کے مطابق، StreamBuilder FutureBuilder اور LayoutBuilder کے ساتھ تین سب سے زیادہ استعمال ہونے والے Builder ویجیٹس میں سے ایک ہے۔

خلاصہ: StreamBuilder ہر وہاں استعمال کریں جہاں UI کو مسلسل بدلتے ڈیٹا کی عکاسی کرنی ہو، StatefulWidget کے ذریعے دستی سٹیٹ مینجمنٹ سے گریز کرتے ہوئے۔

StreamBuilder کیسے کام کرتا ہے

StreamBuilder تعمیر کے وقت Stream کو سبسکرائب کرتا ہے اور ویجیٹ کے تباہ ہونے پر سبسکرپشن ختم کر دیتا ہے۔ جب بھی Stream کوئی ایونٹ جاری کرتا ہے، StreamBuilder ایک نیا AsyncSnapshot حاصل کرتا ہے اور UI کو دوبارہ تعمیر کرنے کے لیے builder فنکشن کو کال کرتا ہے۔

یہ عمل تین مراحل پر مشتمل ہے۔ پہلا: StreamBuilder stream.listen طریقہ کے ذریعے منتقل کردہ Stream کی سبسکرپشن بناتا ہے۔ دوسرا: ہر ایونٹ پر، StreamBuilder اندرونی AsyncSnapshot کو اپ ڈیٹ کرتا ہے اور ویجیٹ کو دوبارہ تعمیر کے لیے گندا نشان زد کرتا ہے۔ تیسرا: فریم ورک builder فنکشن کو نئے سنیپ شاٹ کے ساتھ کال کرتا ہے، اور UI موجودہ ڈیٹا دکھاتا ہے۔

اہم: StreamBuilder اندرونی طور پر StreamSubscription استعمال کرتا ہے۔ اگر Stream براہ راست منتقل کیا جاتا ہے، StreamBuilder ابتدا کے دوران ایک بار سبسکرائب کرتا ہے۔ اگر Stream تبدیل ہوتا ہے (مثال کے طور پر، والدین کی دوبارہ تعمیر کے دوران)، StreamBuilder پرانی اسٹریم سے سبسکرپشن ختم کرتا ہے اور نئی میں سبسکرائب کرتا ہے۔ یہ رویہ initialData اور buildWhen پیرامیٹرز کے ذریعے کنٹرول کیا جاتا ہے، جو دوبارہ تعمیر کی تعداد کو بہتر بنانے کی اجازت دیتے ہیں۔

خلاصہ: سبسکرپشن لائف سائیکل کو سمجھنا StreamBuilder کے صحیح استعمال کی بنیاد ہے۔ غلط اسٹریم مینجمنٹ میموری لیک یا UI میں پرانے ڈیٹا کا باعث بنتی ہے۔

ConnectionState: اسٹریم کی چار حالتیں

AsyncSnapshot آبجیکٹ کی connectionState پراپرٹی یہ طے کرتی ہے کہ StreamBuilder اسٹریم پروسیسنگ کے کس مرحلے پر ہے۔ چار حالتیں ہیں: none، waiting، active، done۔

ConnectionState.none

None ابتدائی حالت ہے جب Stream نے ابھی ڈیٹا منتقل کرنا شروع نہیں کیا۔ اس حالت میں، snapshot.connectionState ConnectionState.none کے برابر ہے اور snapshot.data null ہے۔ عام طور پر اس حالت میں ایک پلیس ہولڈر یا انتظار کا اشارہ دکھایا جاتا ہے۔ اگر Stream ابتدائی ڈیٹا فراہم نہیں کرتا، StreamBuilder اس حالت سے شروع ہوتا ہے۔

ConnectionState.waiting

Waiting غیر متزامن اسٹریم سے ڈیٹا کے انتظار کی حالت ہے۔ Stream فعال ہے، لیکن ڈیٹا ابھی تک نہیں پہنچا۔ یہ حالت، مثال کے طور پر، نیٹ ورک سے ڈیٹا لوڈ کرتے وقت یا طویل مدتی کنکشن کھولتے وقت پیدا ہوتی ہے۔ اس حالت میں عام طور پر CircularProgressIndicator یا کنکال لوڈر دکھایا جاتا ہے۔

ConnectionState.active

Active — اسٹریم ڈیٹا جاری کر رہا ہے اور UI موجودہ معلومات دکھا رہا ہے۔ اس حالت میں، snapshot.hasData درست ہے اور snapshot.data میں اسٹریم کی تازہ ترین قدر ہوتی ہے۔ اگر اسٹریم Broadcast Stream ہے، تو فعال حالت نئے ڈیٹا کے انتظار کے ساتھ ایک ساتھ رہ سکتی ہے۔

ConnectionState.done

Done — اسٹریم مکمل ہو گیا، نیا ڈیٹا نہیں آئے گا۔ Snapshot.data میں اسٹریم بند ہونے سے پہلے منتقل کردہ آخری قدر ہوتی ہے۔ اگر اسٹریم کامیابی سے مکمل ہوا، تو snapshot.hasError غلط ہے۔ یہ حالت حتمی نتیجہ دکھانے کے لیے استعمال ہوتی ہے: “لوڈنگ مکمل” جیسا پیغام یا اگلی اسکرین پر منتقلی۔

خلاصہ: StreamBuilder کے ذریعے UI تعمیر کرتے وقت، چاروں حالتوں کو ہینڈل کرنا ضروری ہے تاکہ انٹرفیس لوڈنگ، ڈیٹا، غلطیاں اور تکمیل کو صحیح طور پر دکھائے۔

اسٹریم کے انتظام کے لیے StreamController کا استعمال

StreamController dart:async پیکیج کی ایک کلاس ہے جو Stream بناتی اور سنبھالتی ہے۔ StreamController ڈیٹا شامل کرنے، غلطیوں کو ہینڈل کرنے اور اسٹریم کو بند کرنے، اس کے لائف سائیکل کو کنٹرول کرنے کی اجازت دیتا ہے۔

StreamController دو قسم کا ہوتا ہے: single-subscription (ایک سبسکرائبر) اور broadcast (متعدد سبسکرائبرز)۔ Single-subscription کنٹرولر ایک وقت میں صرف ایک سننے والے کو قبول کرتا ہے — دوسری سبسکرپشن ایک استثناء پھینکے گی۔ Broadcast کنٹرولر متعدد StreamBuilder کو ایک ساتھ ایک ہی اسٹریم سننے کی اجازت دیتا ہے، جو BLoC اور مشترکہ ایپلیکیشن سٹیٹ کے لیے مفید ہے۔

StreamController<T>.broadcast() کے ذریعے StreamController بناتے وقت، پہلی سبسکرپشن سے پہلے شامل کردہ ڈیٹا نئے سبسکرائبرز کو دوبارہ نہیں چلایا جاتا۔ کنیکٹ ہونے پر تازہ ترین قدر حاصل کرنے کے لیے، rxdart پیکیج کا BehaviourSubject استعمال کیا جاتا ہے، جو آخری ایونٹ کو کیش کرتا ہے۔

کنٹرولر کے ساتھ کام ختم کرنے کے بعد، controller.close() کال کرنا ضروری ہے۔ close کو نہ کال کرنے سے وسائل لیک ہوتے ہیں: اسٹریم کھلا رہتا ہے، سبسکرائبرز میموری میں رہتے ہیں اور GC متعلقہ آبجیکٹس کو آزاد نہیں کرتا۔

خلاصہ: StreamController کو واضح لائف سائیکل مینجمنٹ کے ساتھ استعمال کریں۔ Single-subscription اسٹریمز کے لیے معیاری کنٹرولر، مشترکہ سٹیٹ کے لیے broadcast کنٹرولر یا BehaviourSubject استعمال کریں۔

StreamBuilder کے ساتھ کوڈ کی مثالیں

مثال 1 StreamController اور StreamBuilder کا استعمال کرتے ہوئے الٹی گنتی ٹائمر دکھاتی ہے۔

dart
import 'dart:async';

class TimerWidget extends StatefulWidget {
  const TimerWidget({super.key});

  final StreamController<int> controller = StreamController<int>();

  void startTimer() {
    int count = 0;
    Timer.periodic(Duration(seconds: 1), (timer) {
      controller.sink.add(count++);
      if (count > 10) {
        controller.close();
        timer.cancel();
      }
    });
  }
}

مثال میں، 1 سیکنڈ کے وقفے سے 0 سے 10 تک نمبر پیدا کرنے کے لیے ایک کنٹرولر بنایا گیا ہے۔ 10 تک پہنچنے کے بعد، close کال کیا جاتا ہے اور اسٹریم ختم ہو جاتا ہے۔ اس کنٹرولر کی اسٹریم کو سبسکرائب کرنے والا StreamBuilder ہر نئی قدر دکھائے گا۔

مثال 2 — متعدد ذرائع سے ڈیٹا دکھانے کے لیے Broadcast Stream کے ساتھ StreamBuilder کا استعمال۔

dart
final StreamController<String> broadcastController =
    StreamController<String>.broadcast();

StreamBuilder<String>(
  stream: broadcastController.stream,
  initialData: 'Waiting for data...',
  builder: (context, AsyncSnapshot<String> snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      return const Center(
        child: CircularProgressIndicator(),
      );
    }
    if (snapshot.hasError) {
      return Text('غلطی: ${snapshot.error}');
    }
    return Text('ڈیٹا: ${snapshot.data}');
  },
)

دوسری مثال تمام حالتوں کو ہینڈل کرنا دکھاتی ہے: ابتدائی ڈسپلے کے لیے initialData، لوڈنگ انڈیکیٹر کے لیے waiting، غلطیوں کے لیے hasError اور کامیاب نتیجے کے لیے data۔ یہ پیٹرن StreamBuilder کے ساتھ پروڈکشن کوڈ کا معیار ہے۔

خلاصہ: پہلے لمحے خالی اسکرین سے بچنے کے لیے initialData استعمال کریں اور صارف کو غلطیاں صحیح دکھانے کے لیے ہمیشہ hasError کو ہینڈل کریں۔

StreamBuilder کے ساتھ کام کرتے وقت عام غلطیاں

غلطی 1: ہر والدین کی دوبارہ تعمیر پر نیا Stream بنانا۔ اگر Stream ایک ایسے اظہار کے ذریعے منتقل کیا جاتا ہے جو ہر تعمیر پر نیا آبجیکٹ بناتا ہے، StreamBuilder پرانی سے سبسکرپشن ختم کرتا ہے اور نئی اسٹریم میں سبسکرائب کرتا ہے، جس سے لامتناہی دوبارہ تعمیر کا لوپ بنتا ہے۔ حل: ایک remembered متغیر یا مقررہ Stream کے ساتھ StatefulWidget استعمال کریں۔

غلطی 2: غلطی کے انتظام کی کمی۔ Stream controller.sink.addError کے ذریعے غلطیاں جاری کر سکتا ہے، اور اگر builder snapshot.hasError کو چیک نہیں کرتا، صارف خالی اسکرین یا لامتناہی لوڈنگ دیکھتا ہے۔ حل: ہمیشہ hasError چیک کریں اور واضح پیغام دکھائیں۔

غلطی 3: بند نہ کیے گئے StreamController کی وجہ سے میموری لیک۔ اگر کنٹرولر dispose میں بند نہیں کیا جاتا، اسٹریم موجود رہتا ہے اور GC میموری آزاد نہیں کرتا۔ حل: dispose میں controller.close() کال کریں اور آخری کارروائیوں کے لیے done ایونٹ سنیں۔

غلطی 4: سست builder فنکشن کے ساتھ StreamBuilder کا استعمال۔ چونکہ builder ہر اسٹریم ایونٹ پر کال کیا جاتا ہے، اس کے اندر بھاری حسابات فریم ڈراپ کا سبب بنتے ہیں۔ حل: حسابات کو علیحدہ isolate میں منتقل کریں یا ڈیٹا کی تبدیلی کے لیے Stream.map استعمال کریں۔

خلاصہ: StreamBuilder ایک طاقتور لیکن مطالبہ کرنے والا آلہ ہے۔ Stream لائف سائیکل کی نگرانی کریں، غلطیوں کو ہینڈل کریں اور builder میں بھاری کارروائیوں سے گریز کریں۔

اکثر پوچھے گئے سوالات

StreamBuilder FutureBuilder سے کیسے مختلف ہے؟

FutureBuilder ایک غیر متزامن نتیجے کے لیے ڈیزائن کیا گیا ہے: یہ Future کو سبسکرائب کرتا ہے، ایک قدر حاصل کرتا ہے اور ختم ہو جاتا ہے۔ StreamBuilder ایک Stream کو سبسکرائب کرتا ہے، جو وقت کے ساتھ متعدد قدریں جاری کر سکتا ہے، اور ہر نئے ایونٹ پر UI کو دوبارہ تعمیر کرتا ہے۔

StreamBuilder میں AsyncSnapshot کیا ہے؟

AsyncSnapshot ایک ناقابل تبدیلی آبجیکٹ ہے جس میں موجودہ سبسکرپشن حالت (connectionState)، آخری موصول شدہ قدر (data) اور غلطی کا آبجیکٹ (error) ہوتا ہے اگر اسٹریم نے استثناء جاری کیا ہو۔

StreamBuilder میں غلطیوں کو کیسے ہینڈل کریں؟

غلطیاں builder فنکشن میں snapshot.hasError اور snapshot.error خصوصیات کے ذریعے ہینڈل کی جاتی ہیں۔ اگر اسٹریم sink.addError کے ذریعے غلطی جاری کرتا ہے، AsyncSnapshot غلطی حاصل کرتا ہے، اور builder کو مناسب پیغام یا فال بیک UI دکھانا چاہیے۔

کیا ایک Stream کو متعدد StreamBuilder میں استعمال کیا جا سکتا ہے؟

ہاں، اگر Stream broadcast ہے (StreamController.broadcast کے ذریعے بنایا گیا)۔ Single-subscription Stream صرف ایک سبسکرائبر کی اجازت دیتا ہے۔ متعدد ویجیٹس کے درمیان ایک اسٹریم شیئر کرنے کے لیے، broadcast کنٹرولر یا BehaviourSubject کے ساتھ rxdart پیکیج استعمال کریں۔

ہر ایونٹ پر StreamBuilder کی دوبارہ تعمیر سے کیسے بچیں؟

UI دوبارہ تعمیر کو متحرک کرنے والے ایونٹس کو فلٹر کرنے کے لیے buildWhen پیرامیٹر استعمال کریں۔ StreamBuilder کو ڈیٹا منتقل کرنے سے پہلے فلٹر کرنے کے لیے Stream.transformer یا Stream.where بھی لگائیں۔

خلاصہ

  • StreamBuilder — غیر متزامن ڈیٹا اسٹریم سے ری ایکٹیو UI تعمیر کے لیے ایک ویجیٹ، مسلسل انٹرفیس اپ ڈیٹس کو سپورٹ کرتا ہے
  • AsyncSnapshot میں connectionState (none، waiting، active، done)، data اور error ہوتا ہے — تمام اسٹریم حالتیں
  • StreamController اسٹریم لائف سائیکل کا انتظام کرتا ہے: ڈیٹا شامل کرنا، غلطیاں ہینڈل کرنا، اور اسٹریم بند کرنا
  • Broadcast Stream متعدد StreamBuilder کو ایک اسٹریم سبسکرائب کرنے دیتا ہے، single-subscription صرف ایک کو
  • غلطی کا انتظام لازمی ہے: hasError کی جانچ کے بغیر، ایپ لوڈنگ کی حالت میں پھنس سکتی ہے
  • میموری لیک سب سے عام مسئلہ ہے: ہمیشہ dispose میں StreamController بند کریں
  • سفارش: ہمیشہ initialData متعین کریں اور ہموار UX کے لیے چاروں connectionState قدروں کو ہینڈل کریں

ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے

IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔

پروجیکٹ پر بحث کریں

مزید پڑھیں