BLoC (Business Logic Component) — Google tərəfindən 2018-ci ildə DartConf-da təqdim edilmiş Flutter üçün vəziyyətin idarə edilməsi nümunəsi. BLoC reaktiv axınlar (Stream) vasitəsilə biznes məntiqini və istifadəçi interfeysini ayırır: UI Event göndərir, BLoC onu emal edir və Stream vasitəsilə yeni State qaytarır. pub.dev məlumatlarına görə, flutter_bloc paketi 11 mindən çox bəyənmə toplayıb və minlərlə Flutter tətbiqində istifadə olunur.
Əsas məqamlar
BLoC (Business Logic Component) — Flutter üçün memarlıq nümunəsi olub, biznes məntiqi UI-dan ayrılmış ayrıca sinfə çıxarılır. BLoC giriş məlumatlarını hadisələr axını (Event) vasitəsilə qəbul edir və vəziyyət axını (State) vasitəsilə çıxış məlumatlarını verir. Təqdimat təbəqəsi (Widget) yalnız State axınına abunə olur və UI-ni göstərir, heç vaxt birbaşa biznes məntiqini yerinə yetirmir.
BLoC konsepsiyası reaktiv proqramlaşdırma və Observer nümunəsinə əsaslanır. Hər BLoC komponenti dəqiq kontraktı olan ayrıca moduldur: Event dəsti (nə baş verə bilər) və State dəsti (nə göstərilə bilər) məlumdur. Tərtibatçı UI-dan "təsadüfən" vəziyyəti dəyişə bilməz — yalnız konkret Event vasitəsilə. Bu, kodu proqnozlaşdırıla bilən və test edilə bilən edir.
Flutter Community 2025 sorğusuna görə, BLoC Provider-dən sonra Flutter-də vəziyyətin idarə edilməsi həlləri arasında populyarlığa görə ikinci yerdədir. Əsas üstünlüklər: ciddi tipizasiya, məntiqin izolyasiyası, daxili Stream dəstəyi, zəngin alət ekosistemi (BlocProvider, BlocListener, BlocSelector).
BLoC arxitekturası üç varlıq ətrafında qurulur: Event (giriş), Bloc (emal edən) və State (çıxış). Widget add() metodu vasitəsilə Event göndərir. Bloc Event-i mapEventToState və ya on<Event> metodunda qəbul edir, biznes məntiqini yerinə yetirir və yield vasitəsilə yeni State verir. Widget State-i Stream vasitəsilə alır və yenidən çəkir.
abstract class CounterEvent {}
class Increment extends CounterEvent {}
class Decrement extends CounterEvent {}
class CounterBloc extends Bloc<CounterEvent, int> {
CounterBloc() : super(0);
@override
Stream<int> mapEventToState(CounterEvent event) async* {
if (event is Increment) {
yield state + 1;
} else if (event is Decrement) {
yield state - 1;
}
}
}Tip təhlükəsizliyi: Bloc iki tiplə parametrləşdirilir — Event və State. Dart kompilyatoru Widget-in yalnız elan edilmiş Event-ləri çağırdığını, Bloc-un isə yalnız elan edilmiş State-ləri qaytardığını yoxlayır. "Naməlum Əməliyyat" tipli icra xətaları istisna edilir.
Close və Dispose: Bloc Closeable interfeysini tətbiq edir. Vidjet məhv edildikdə, Bloc avtomatik olaraq close() metodu vasitəsilə Stream-i bağlayır. Reaktiv abunəlik sızmaları mümkün deyil — BlocProvider Bloc-un həyat dövrünü idarə edir, onu rout və ya səhifə ilə əlaqələndirir.
Cubit — flutter_bloc 6.0 paketində təqdim edilmiş Event-siz Bloc-un sadələşdirilmiş tətbiqi. Cubit siniflər əvəzinə birbaşa metodlar elan edir: increment(), fetchData(). Daxili olaraq Cubit eyni Stream mexanizmindən istifadə edir, lakin Event qatını gizlədir. Bu, sadə ssenarilər üçün boilerplate-i 40-50% azaldır.
| Xüsusiyyət | Bloc | Cubit |
|---|---|---|
| Event sinifləri | Məcburi | Lazım deyil |
| Boilerplate | Yüksək | Aşağı |
| Əməliyyat izləmə | Event tipi ilə | Yalnız metod adı |
| Uyğundur | Mürəkkəb ssenarilər | Sadə vəziyyətlər |
| Analitika | Event üzrə avtomatik | Əl ilə |
Nə vaxt Cubit seçməli: 2-3 variantlı vəziyyət (loading, loaded, error), sadə formalar, sayğaclar, UI vəziyyətləri (açıq/bağlı). Nə vaxt Bloc: çoxsaylı hərəkətləri olan mürəkkəb biznes məntiqi: sifarişin verilməsi, avtorizasiya, məlumat sinxronizasiyası. Bloc hər bir əməliyyatın Event vasitəsilə detallı izlənməsini təmin edir — hər çağırış BlocObserver-da qeydə alınır.
BlocObserver — tətbiqdəki bütün Bloc və Cubit-ləri izləyən qlobal müşahidəçi. Event, State, xəta və keçidləri qeyd etməyə imkan verir. Bir nümunəni qoşmaq kifayətdir: Bloc.observer = AppBlocObserver() və tətbiqin vəziyyətinin bütün izlənməsi mərkəzləşdirilmiş şəkildə mövcuddur.
BlocProvider — flutter_bloc-dən InheritedWidget, Bloc-u uşaq vidjetlərə təqdim edir. Vidjetin başlanğıcında BlocProvider Bloc yaradır, məhv edildikdə isə close() vasitəsilə avtomatik bağlayır. BlocProvider MaterialApp səviyyəsində (qlobal Bloc) və ya konkret rout səviyyəsində (lokal Bloc) yerləşdirilə bilər.
BlocProvider(
create: (context) => CounterBloc(),
child: Column(
children: [
BlocBuilder<CounterBloc, int>(
builder: (context, state) => Text('$state'),
),
ElevatedButton(
onPressed: () => context.read<CounterBloc>().add(Increment()),
child: Text('+'),
),
],
),
)BlocBuilder — hər yeni State-də UI-ni yenidən quran vidjet. BlocListener — yan təsirlər üçün (State-i bir dəfə emal etmək, UI-ni yenidən qurmadan): SnackBar göstərmək, başqa ekrana naviqasiya etmək. BlocConsumer — həm yenidənqurma, həm də yan təsir lazım olduqda Builder və Listener-in kombinasiyası. BlocSelector — yalnız State-in konkret sahəsi dəyişdikdə seçmə yenidənqurma üçün.
MultiBlocProvider — iç-içə BlocProvider-lər üçün vidjet, iç-içəlik səviyyəsini artırmadan. 10-15 Bloc olan Flutter tətbiqi bütün tətbiq üçün əlçatan olan bütün Bloc-ları qeydiyyatdan keçirmək üçün kök səviyyədə MultiBlocProvider istifadə edir: AuthenticationBloc, CartBloc, SettingsBloc.
BLoC test edilir Flutter vidjetləri olmadan izolə şəkildə. Dart paketi flutter_test və bloc_test paketini idxal etmək kifayətdir. Test ssenarisi: Bloc yaratmaq, Event əlavə etmək, State-i yoxlamaq. blocTest — ardıcıllığı avtomatlaşdıran vasitə: build → act → expect.
blocTest<CounterBloc, int>(
'emits [1] when Increment is added',
build: () => CounterBloc(),
act: (bloc) => bloc.add(Increment()),
expect: () => [1],
)Mocking: Repozitoriya və ya API-dən asılı olan BLoC mocktail vasitəsilə mock-larla test edilir. Repozitoriya abstraksiya səviyyəsində mock edilir, Bloc mock edilmiş asılılıqları konstruktor vasitəsilə alır. Hydrated Bloc — yerli yaddaşda vəziyyətin avtomatik saxlanması/bərpası üçün genişləndirmə. HydratedBlocStorage və müvəqqəti fayl yaddaşı ilə test edilir.
Qovluq və fayllar: BLoC-da Flutter layihəsinin tipik strukturu: bloc/counter_bloc.dart, bloc/counter_event.dart, bloc/counter_state.dart. 30+ ekran üçün funksiyalara görə qruplaşdırma tövsiyə olunur: features/auth/bloc/, features/cart/bloc/. Hər Bloc ayrıca fayl, hər Event və State — ya ayrıca fayllarda, ya da Bloc ilə bir faylda.
Performans: BLoC boş Stream-lər üzərində əlavə yük yaratmır. BlocBuilder yenidənqurmaları filtrləmək üçün buildWhen istifadə edir — vidjet yalnız konkret şərt dəyişdikdə yenilənir. Close aktiv olmayan Bloc-ların yaddaş sərf etməməsinə zəmanət verir. Flutter DevTools məlumatlarına görə, BLoC paket ölçüsünə 1%-dən az əlavə edir.
Provider-dən miqrasiya: BLoC eyni layihədə Provider ilə asanlıqla birgə mövcud ola bilər. Mərhələli miqrasiya: əvvəlcə ən mürəkkəb Provider-lər Bloc ilə əvəz olunur, sonra qalanları. BlocProvider Provider ağacı ilə uyğundur: köhnə vidjetlər Provider, yeniləri — BlocProvider, eyni tətbiqdə istifadə edə bilər.
Tez-tez verilən suallar
BLoC biznes məntiqinin izolyasiyası və ciddi tipizasiya üçün Event + Stream istifadə edir. Provider — asılılıqların sadə yeridilməsi və ChangeNotifier üçün InheritedWidget üzərində qat. BLoC çoxsaylı vəziyyətləri olan mürəkkəb ssenarilər üçün daha uyğundur, Provider — lokal UI vəziyyəti üçün. BLoC daha çox boilerplate tələb edir, lakin Event vasitəsilə tam izlənmə qabiliyyəti verir.
Hydrated Bloc — hydrated_bloc paketindən genişləndirmə, son State-i lokal yaddaşda avtomatik saxlayır (standart olaraq Hive). Tətbiq yenidən başladıqda Bloc ilkin vəziyyət əvəzinə saxlanmış vəziyyəti bərpa edir. Bu, əl ilə saxlama çağırışı olmadan davamlılıq məsələsini həll edir: giriş, səbət, parametrlər sessiyalar arasında avtomatik saxlanılır.
BLoC-da xəta mapEventToState və ya on<Event> daxilində try-catch vasitəsilə idarə olunur. Xəta olduqda Bloc xəta State-i qaytarır: yield LoadError(error.message). UI-də BlocListener və ya BlocConsumer State-i xəta tipinə görə yoxlayır və SnackBar və ya dialoq göstərir. BlocObserver qlobal olaraq bütün idarə olunmamış istisnaları qeyd edir.
BLoC — Flutter-spesifik nümunədir, çünki Dart Stream və Flutter vidjetlərindən istifadə edir. Event → Bloc → State konsepsiyası AngularDart və Server-side Dart üçün uyğunlaşdırıla bilər, lakin əsas ekosistem (BlocProvider, BlocBuilder, BlocObserver) Flutter-ə bağlıdır. React Native üçün Redux və ya MobX, SwiftUI üçün Combine + MVVM istifadə edin.
Cubit — sadə vəziyyətlər üçün (sayğac, toggle, 2-3 sahəli forma). Bloc — mürəkkəb məntiq üçün (xəbər lenti, sifarişin verilməsi, avtorizasiya). Əsas qayda: analitika və ya sazlama üçün hər bir hərəkətin (Event) izlənməsi lazımdırsa — Bloc. Vəziyyəti dəyişən metodlar kifayətdirsə — Cubit. Hər iki nümunə eyni layihədə birgə mövcud ola bilər.
Nəticə
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