StreamBuilder — asinxron axından yeni məlumatlar alındıqda interfeysi avtomatik yenidən quran Flutter vidjeti. FutureBuilder-dən fərqli olaraq, bir dəfəlik nəticə ilə işləyən StreamBuilder, Stream-in bütün həyat dövrü ərzində UI-nin fasiləsiz yenilənməsini dəstəkləyir. Flutter (2026) rəsmi sənədlərinə görə, StreamBuilder real vaxt tətbiqlərində istifadə olunur: çatlar, xəbər lentləri, sensor monitorinqi və maliyyə tickerləri. Bu, UI-nin əl ilə setState çağırışları olmadan məlumatların vəziyyətini əks etdirdiyi reaktiv proqramlaşdırmanın əsas alətidir.
Əsas məqamlar
StreamBuilder — Flutter SDK paketindən olan, Stream-ə abunə olan və axının hər yeni hadisəsində öz uşaq elementini yenidən quran vidjetdir. StreamBuilder Stream obyektini qəbul edir və axından alınan son snapshot əsasında widget qaytarır.
Flutter arxitekturasında StreamBuilder, UI quruluşunu məlumatların vəziyyətindən ayıran Builder-vidjetlər qrupuna aiddir. Vəziyyətin dəyişdirilməsi açıq setState çağırışı tələb edən StatefulWidget-dən fərqli olaraq, StreamBuilder asinxron hadisələrə avtomatik reaksiya verir, bu da kodu sadələşdirir və sinxronizasiya səhvləri riskini azaldır.
FutureBuilder-dən fərqli olaraq, tək asinxron dəyəri emal edən StreamBuilder fasiləsiz məlumat axınları üçün nəzərdə tutulmuşdur. FutureBuilder ilk nəticəni aldıqdan sonra tamamlanır, StreamBuilder isə axını dinləməyə davam edir və hər yeni hadisədə UI-ni yeniləyir.
StreamBuilder məlumatların fasiləsiz daxil olduğu bütün ssenarilərdə tətbiq olunur: WebSocket bağlantıları, sensor çağırışları, Firebase bildirişləri, Bluetooth hadisə növbələri və BLoC vasitəsilə tətbiq vəziyyətinin yayımlanması. GitHub-da (2025) Flutter layihələrinin təhlilinə görə, StreamBuilder FutureBuilder və LayoutBuilder ilə yanaşı ən çox istifadə olunan Builder-vidjetlər üçlüyünə daxildir.
Nəticə: StatefulWidget vasitəsilə əl ilə vəziyyət idarəçiliyindən qaçaraq, UI-nin davamlı dəyişən məlumatları əks etdirməli olduğu hər yerdə StreamBuilder istifadə edin.
StreamBuilder qurulma anında Stream-ə abunə olur və vidjet məhv edildikdə abunəni ləğv edir. Stream hər dəfə hadisə göndərdikdə, StreamBuilder yeni AsyncSnapshot alır və UI-ni yenidən qurmaq üçün builder funksiyasını çağırır.
Proses üç mərhələdən ibarətdir. Birinci: StreamBuilder stream.listen metodu vasitəsilə ötürülən Stream-ə abunə yaradır. İkinci: hər hadisədə StreamBuilder daxili AsyncSnapshot-i yeniləyir və vidjeti yenidən qurulma üçün “çirkli” olaraq qeyd edir. Üçüncü: framework yeni snapshot ilə builder funksiyasını çağırır və UI cari məlumatları göstərir.
Vacib: StreamBuilder daxili olaraq StreamSubscription istifadə edir. Stream birbaşa ötürülürsə, StreamBuilder inisiallaşdırmada bir dəfə abunə olur. Stream dəyişərsə (məsələn, valideynin yenidən qurulması zamanı), StreamBuilder köhnə axından abunəni ləğv edir və yenisinə abunə olur. Bu davranış ilkinData və buildWhen parametrləri ilə idarə olunur ki, bu da yenidənqurma sayını optimallaşdırmağa imkan verir.
Nəticə: abunənin həyat dövrünü başa düşmək StreamBuilder-in düzgün istifadəsinin əsasıdır. Axınların düzgün idarə edilməməsi yaddaş sızmalarına və ya UI-də köhnəlmiş məlumatlara səbəb olur.
AsyncSnapshot obyektinin connectionState xassəsi StreamBuilder-in axınla işin hansı mərhələsində olduğunu müəyyən edir. Dörd vəziyyət fərqləndirilir: none, waiting, active, done.
None — Stream hələ məlumat ötürməyə başlamadıqda ilkin vəziyyət. Bu vəziyyətdə snapshot.connectionState ConnectionState.none bərabərdir, snapshot.data isə null-dur. Adətən bu vəziyyətdə placeholder və ya ilk hadisənin gözləməsi göstərilir. Stream ilkin məlumat təqdim etmirsə, StreamBuilder bu vəziyyətdən başlayır.
Waiting — asinxron axından məlumat gözləmə vəziyyəti. Stream aktivdir, lakin məlumatlar hələ daxil olmayıb. Bu vəziyyət, məsələn, şəbəkədən məlumat yüklənərkən və ya uzunmüddətli əlaqə açılarkən yaranır. Bu vəziyyətdə adətən CircularProgressIndicator və ya yükləmə skeleti göstərilir.
Active — axın məlumat göndərir və UI cari məlumatı göstərir. Bu vəziyyətdə snapshot.hasData true, snapshot.data isə axındakı son dəyəri ehtiva edir. Stream Broadcast Stream-dirsə, aktiv vəziyyət yeni məlumatların gözləməsi ilə birgə mövcud ola bilər.
Done — axın tamamlandı, yeni məlumat olmayacaq. Snapshot.data axının bağlanmasından əvvəl ötürülən son dəyəri ehtiva edir. Axın uğurla tamamlanıbsa, snapshot.hasError false-dur. Bu vəziyyət son nəticəni göstərmək üçün istifadə olunur: “Yükləmə tamamlandı” mesajı və ya növbəti ekrana keçid.
Nəticə: StreamBuilder vasitəsilə UI qurarkən, interfeysin yükləmə, məlumat, səhv və tamamlanmanı düzgün göstərməsi üçün bütün dörd vəziyyəti emal etmək lazımdır.
StreamController — dart:async paketindən Stream yaradan və idarə edən sinif. StreamController məlumatları əlavə etməyə, səhvləri emal etməyə və axını bağlamağa, onun həyat dövrünü idarə etməyə imkan verir.
StreamController iki növdə olur: single-subscription (bir abunəçi) və broadcast (çoxsaylı abunəçi). Single-subscription nəzarətçi bir dəfəyə yalnız bir dinləyici qəbul edir — təkrar abunəlik istisnaya səbəb olur. Broadcast nəzarətçi bir neçə StreamBuilder-ə eyni anda bir axını dinləməyə imkan verir ki, bu da BLoC və tətbiqin ümumi vəziyyəti üçün faydalıdır.
StreamController<T>.broadcast() vasitəsilə StreamController yaradılarkən, ilk abunədən əvvəl əlavə edilən məlumatlar yeni abunəçiyə təkrarlanmır. Qoşulma zamanı son dəyəri əldə etmək lazımdırsa, son hadisəni keşləyən rxdart paketindən BehaviourSubject istifadə olunur.
Nəzarətçi ilə işi bitirdikdən sonra controller.close() çağırılmalıdır. Close çağırılmaması resurs sızmasına səbəb olur: axın açıq qalır, abunəçilər yaddaşda qalır və GC əlaqəli obyektləri azad etmir.
Nəticə: StreamController-i açıq həyat dövrü idarəçiliyi ilə istifadə edin. Single-subscription axınları üçün standart nəzarətçi, paylaşılan vəziyyət üçün broadcast nəzarətçi və ya BehaviourSubject istifadə edin.
Nümunə 1 StreamController və StreamBuilder istifadə edərək geri sayım taymerini nümayiş etdirir.
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();
}
});
}
}
Nümunədə 1 saniyə intervalı ilə 0-dan 10-a qədər rəqəmlər yaratmaq üçün nəzarətçi yaradılır. 10-a çatdıqdan sonra close çağırılır və axın tamamlanır. Bu nəzarətçinin stream-inə abunə olan StreamBuilder hər yeni dəyəri göstərəcək.
Nümunə 2 — çoxsaylı mənbələrdən məlumatları göstərmək üçün Broadcast Stream ilə StreamBuilder istifadəsi.
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('Error: ${snapshot.error}');
}
return Text('Data: ${snapshot.data}');
},
)
İkinci nümunə bütün vəziyyətlərin emalını göstərir: ilkin göstərmə üçün initialData, yükləmə göstəricisi üçün waiting, səhvlər üçün hasError və uğurlu nəticə üçün data. Bu naxış StreamBuilder ilə istehsal kodunun standartıdır.
Nəticə: ilk anda boş ekrandan qaçmaq üçün initialData istifadə edin və səhvləri istifadəçiyə düzgün göstərmək üçün həmişə hasError-ı emal edin.
Səhv 1: valideynin hər yenidən qurulmasında yeni Stream yaratmaq. Stream hər qurulmada yeni obyekt yaradan ifadə vasitəsilə ötürülürsə, StreamBuilder köhnədən abunəni ləğv edir və yeni axına abunə olur, sonsuz yenidənqurma dövrünə səbəb olur. Həll yolu: remembered dəyişəni və ya sabit Stream ilə StatefulWidget istifadə edin.
Səhv 2: səhv emalının olmaması. Stream controller.sink.addError vasitəsilə səhvlər göndərə bilər və builder snapshot.hasError-ı yoxlamazsa, istifadəçi boş ekran və ya sonsuz yükləmə görür. Həll yolu: həmişə hasError-ı yoxlayın və başa düşülən mesaj göstərin.
Səhv 3: bağlanmamış StreamController səbəbindən yaddaş sızması. Nəzarətçi dispose-da bağlanmazsa, axın mövcud olmağa davam edir və GC yaddaşı azad etmir. Həll yolu: dispose-da controller.close() çağırın və tamamlama hərəkətləri üçün done hadisəsini dinləyin.
Səhv 4: yavaş builder funksiyası ilə StreamBuilder istifadəsi. Builder axının hər hadisəsində çağırıldığından, onun içindəki ağır hesablamalar kadrların buraxılmasına səbəb olur. Həll yolu: hesablamaları ayrıca izolyata çıxarın və ya məlumatları çevirmək üçün Stream.map istifadə edin.
Nəticə: StreamBuilder güclü, lakin tələbkar alətdir. Stream-in həyat dövrünə nəzarət edin, səhvləri emal edin və builder-də ağır əməliyyatlardan qaçın.
Tez-tez verilən suallar
FutureBuilder bir dəfəlik asinxron nəticə üçün nəzərdə tutulmuşdur: Future-ə abunə olur, bir dəyər alır və işini bitirir. StreamBuilder zaman ərzində çoxsaylı dəyərlər göndərə bilən Stream-ə abunə olur və hər yeni hadisədə UI-ni yenidən qurur.
AsyncSnapshot — cari abunə vəziyyətini (connectionState), son alınan dəyəri (data) və axın istisna göndərdikdə səhv obyektini (error) ehtiva edən dəyişməz obyektdir.
Səhv builder funksiyasında snapshot.hasError və snapshot.error xassələri vasitəsilə emal edilir. Axın sink.addError metodu ilə səhv göndərərsə, AsyncSnapshot error alır və builder müvafiq mesaj və ya fallback UI göstərməlidir.
Bəli, Stream broadcast-dirsə (StreamController.broadcast vasitəsilə yaradılıbsa). Single-subscription Stream yalnız bir abunəçiyə icazə verir. Bir axını bir neçə vidjet arasında bölüşmək üçün broadcast nəzarətçi və ya BehaviourSubject ilə rxdart paketindən istifadə edin.
UI-nin yenidən qurulmalı olduğu hadisələri filtrləmək üçün buildWhen parametrindən istifadə edin. Həmçinin StreamBuilder-ə ötürülməzdən əvvəl məlumatları filtrləmək üçün Stream.transformer və ya Stream.where tətbiq edin.
Xülasə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun