BLoC (Business Logic Component) — Flutter-এর জন্য একটি স্টেট ম্যানেজমেন্ট প্যাটার্ন, যা Google 2018 সালে DartConf-এ উপস্থাপন করে। BLoC রিঅ্যাক্টিভ স্ট্রিম (Stream) এর মাধ্যমে বিজনেস লজিক এবং ইউজার ইন্টারফেসকে আলাদা করে: UI একটি Event পাঠায়, BLoC এটি প্রসেস করে এবং Stream এর মাধ্যমে একটি নতুন State ফেরত দেয়। pub.dev অনুসারে, flutter_bloc প্যাকেজটি 11 হাজারেরও বেশি লাইক পেয়েছে এবং হাজার হাজার Flutter অ্যাপ্লিকেশনে ব্যবহৃত হয়।
মূল পয়েন্ট
BLoC (Business Logic Component) — Flutter-এর জন্য একটি আর্কিটেকচারাল প্যাটার্ন যেখানে বিজনেস লজিককে UI থেকে আলাদা একটি পৃথক ক্লাসে নেওয়া হয়। BLoC ইভেন্টের স্ট্রিম (Event) এর মাধ্যমে ইনপুট ডেটা গ্রহণ করে এবং স্টেটের স্ট্রিম (State) এর মাধ্যমে আউটপুট ডেটা উৎপন্ন করে। প্রেজেন্টেশন লেয়ার (Widget) শুধুমাত্র State স্ট্রিমে সাবস্ক্রাইব করে এবং UI রেন্ডার করে, কখনোই সরাসরি বিজনেস লজিক এক্সিকিউট করে না।
BLoC ধারণাটি রিঅ্যাক্টিভ প্রোগ্রামিং এবং Observer প্যাটার্নের উপর ভিত্তি করে তৈরি। প্রতিটি BLoC উপাদান একটি স্পষ্ট চুক্তি সহ একটি পৃথক মডিউল: Event-এর একটি পরিচিত সেট (কী ঘটতে পারে) এবং State-এর একটি পরিচিত সেট (কী প্রদর্শিত হতে পারে)। একজন ডেভেলপার UI থেকে "দুর্ঘটনাবশত" অবস্থা পরিবর্তন করতে পারে না — শুধুমাত্র একটি নির্দিষ্ট Event-এর মাধ্যমে। এটি কোডকে পূর্বানুমানযোগ্য এবং পরীক্ষাযোগ্য করে তোলে।
Flutter Community 2025 জরিপ অনুসারে, Provider-এর পরে Flutter-এ স্টেট ম্যানেজমেন্ট সমাধানগুলির মধ্যে BLoC দ্বিতীয় স্থানে রয়েছে। প্রধান সুবিধা: স্ট্রং টাইপিং, লজিক আলাদাকরণ, অন্তর্নির্মিত Stream সমর্থন, ইউটিলিটির সমৃদ্ধ ইকোসিস্টেম (BlocProvider, BlocListener, BlocSelector)।
BLoC আর্কিটেকচার তিনটি সত্ত্বাকে ঘিরে নির্মিত: Event (ইনপুট), Bloc (হ্যান্ডলার) এবং State (আউটপুট)। Widget add() মেথডের মাধ্যমে একটি Event পাঠায়। Bloc mapEventToState বা on<Event> মেথডে Event গ্রহণ করে, বিজনেস লজিক এক্সিকিউট করে এবং yield-এর মাধ্যমে একটি নতুন State নির্গত করে। Widget Stream-এর মাধ্যমে State গ্রহণ করে এবং পুনঃনির্মাণ করে।
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;
}
}
}টাইপ সুরক্ষা: Bloc দুটি টাইপ — Event এবং State — দিয়ে প্যারামিটারাইজ করা হয়। Dart কম্পাইলার চেক করে যে Widget শুধুমাত্র ঘোষিত Event-গুলিকে কল করে এবং Bloc শুধুমাত্র ঘোষিত State-গুলিকে ফেরত দেয়। "অজানা অ্যাকশন"-এর মতো রানটাইম ত্রুটিগুলি বাদ দেওয়া হয়।
Close এবং Dispose: Bloc Closeable ইন্টারফেস ইমপ্লিমেন্ট করে। যখন একটি উইজেট ধ্বংস হয়, Bloc স্বয়ংক্রিয়ভাবে close() মেথডের মাধ্যমে Stream বন্ধ করে দেয়। রিঅ্যাক্টিভ সাবস্ক্রিপশন লিক অসম্ভব — BlocProvider Bloc-এর জীবনচক্র পরিচালনা করে, এটিকে একটি রুট বা পৃষ্ঠার সাথে আবদ্ধ করে।
Cubit Event ছাড়া Bloc-এর একটি সরলীকৃত বাস্তবায়ন, যা flutter_bloc 6.0 প্যাকেজে প্রবর্তিত হয়েছে। Cubit Event ক্লাসের পরিবর্তে সরাসরি মেথড ঘোষণা করে: increment(), fetchData()। অভ্যন্তরীণভাবে, Cubit একই Stream-ভিত্তিক পদ্ধতি ব্যবহার করে কিন্তু Event স্তর লুকিয়ে রাখে। এটি সাধারণ পরিস্থিতিতে boilerplate 40-50% হ্রাস করে।
| বৈশিষ্ট্য | Bloc | Cubit |
|---|---|---|
| Event ক্লাস | আবশ্যক | প্রয়োজন নেই |
| Boilerplate | উচ্চ | নিম্ন |
| অ্যাকশন ট্র্যাকিং | Event টাইপের মাধ্যমে | শুধুমাত্র মেথডের নাম |
| এর জন্য উপযুক্ত | জটিল পরিস্থিতি | সাধারণ অবস্থা |
| অ্যানালিটিক্স | Event দ্বারা স্বয়ংক্রিয় | ম্যানুয়াল |
কখন Cubit বেছে নেবেন: 2-3 ভেরিয়েন্ট সহ অবস্থা (লোড হচ্ছে, লোড হয়েছে, ত্রুটি), সাধারণ ফর্ম, কাউন্টার, UI অবস্থা (খোলা/বন্ধ)। কখন Bloc বেছে নেবেন: একাধিক অ্যাকশন সহ জটিল বিজনেস লজিক: অর্ডার প্রসেসিং, অনুমোদন, ডেটা সিঙ্ক্রোনাইজেশন। Bloc Event-এর মাধ্যমে প্রতিটি অ্যাকশনের বিস্তারিত ট্রেসিং প্রদান করে — প্রতিটি কল BlocObserver-এ লগ হয়।
BlocObserver — একটি বৈশ্বিক পর্যবেক্ষক যা অ্যাপ্লিকেশনের সমস্ত Bloc এবং Cubit ট্র্যাক করে। এটি Event, State, ত্রুটি এবং রূপান্তর লগ করার অনুমতি দেয়। শুধু একটি ইনস্ট্যান্স সংযোগ করুন: Bloc.observer = AppBlocObserver(), এবং সম্পূর্ণ অ্যাপ্লিকেশন স্টেট ট্রেসিং কেন্দ্রীয়ভাবে উপলব্ধ।
BlocProvider — flutter_bloc থেকে একটি InheritedWidget যা চাইল্ড উইজেটগুলিকে Bloc সরবরাহ করে। যখন একটি উইজেট আরম্ভ হয়, BlocProvider একটি Bloc তৈরি করে, এবং যখন ধ্বংস হয় — close() এর মাধ্যমে এটি স্বয়ংক্রিয়ভাবে বন্ধ করে দেয়। BlocProvider MaterialApp স্তরে (গ্লোবাল Bloc) বা একটি নির্দিষ্ট রুট স্তরে (লোকাল Bloc) স্থাপন করা যেতে পারে।
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 — একটি উইজেট যা প্রতিটি নতুন State-এ UI পুনর্নির্মাণ করে। BlocListener — সাইড ইফেক্টের জন্য (UI পুনর্নির্মাণ না করে একবার State প্রসেস করুন): SnackBar দেখানো, অন্য স্ক্রিনে নেভিগেট করা। BlocConsumer — Builder এবং Listener-এর সংমিশ্রণ যেখানে পুনর্নির্মাণ এবং সাইড ইফেক্ট উভয়ের প্রয়োজন হয়। BlocSelector — শুধুমাত্র তখন নির্বাচনী পুনর্নির্মাণের জন্য যখন State-এর একটি নির্দিষ্ট ফিল্ড পরিবর্তিত হয়।
MultiBlocProvider — নেস্টিং স্তর না বাড়িয়ে নেস্টেড BlocProvider-এর জন্য একটি উইজেট। 10-15 Bloc সহ একটি Flutter অ্যাপ্লিকেশন সমস্ত Bloc নিবন্ধনের জন্য রুট স্তরে MultiBlocProvider ব্যবহার করে যা সম্পূর্ণ অ্যাপ্লিকেশনের জন্য উপলব্ধ: AuthenticationBloc, CartBloc, SettingsBloc।
BLoC পরীক্ষা Flutter উইজেট ছাড়া বিচ্ছিন্নভাবে করা হয়। শুধু Dart প্যাকেজ flutter_test এবং bloc_test প্যাকেজ আমদানি করুন। পরীক্ষার পরিস্থিতি: Bloc তৈরি করুন, Event যোগ করুন, State যাচাই করুন। blocTest — একটি ইউটিলিটি যা ক্রমটি স্বয়ংক্রিয় করে: build → act → expect।
blocTest<CounterBloc, int>(
'emits [1] when Increment is added',
build: () => CounterBloc(),
act: (bloc) => bloc.add(Increment()),
expect: () => [1],
)মকিং: একটি Bloc যা রিপোজিটরি বা API-এর উপর নির্ভর করে, mocktail-এর মাধ্যমে মক দিয়ে পরীক্ষা করা হয়। রিপোজিটরি অ্যাবস্ট্রাকশন স্তরে মক করা হয়, এবং Bloc কনস্ট্রাক্টরের মাধ্যমে মক করা ডিপেন্ডেন্সি গ্রহণ করে। Hydrated Bloc — লোকাল স্টোরেজে স্বয়ংক্রিয় স্টেট পার্সিস্টেন্স/রিস্টোরেশনের জন্য একটি এক্সটেনশন। এটি HydratedBlocStorage এবং অস্থায়ী ফাইল স্টোরেজ দিয়ে পরীক্ষা করা হয়।
ফোল্ডার এবং ফাইল: BLoC সহ একটি সাধারণ Flutter প্রজেক্ট কাঠামো: bloc/counter_bloc.dart, bloc/counter_event.dart, bloc/counter_state.dart। 30+ স্ক্রিনের জন্য, ফিচার-ভিত্তিক গ্রুপিং সুপারিশ করা হয়: features/auth/bloc/, features/cart/bloc/। প্রতিটি Bloc একটি পৃথক ফাইল, প্রতিটি Event এবং State — হয় পৃথক ফাইলে বা Bloc-এর সাথে একটি ফাইলে।
পারফরম্যান্স: BLoC খালি Stream-এর জন্য ওভারহেড তৈরি করে না। BlocBuilder পুনর্নির্মাণ ফিল্টার করতে buildWhen ব্যবহার করে — উইজেটটি শুধুমাত্র তখন আপডেট হয় যখন একটি নির্দিষ্ট শর্ত পরিবর্তিত হয়। Close নিশ্চিত করে যে নিষ্ক্রিয় Bloc মেমরি ব্যবহার না করে। Flutter DevTools অনুসারে, BLoC বান্ডল সাইজে 1% এর কম যোগ করে।
Provider থেকে মাইগ্রেশন: BLoC একই প্রজেক্টে Provider-এর সাথে সহজেই সহাবস্থান করে। ধীরে ধীরে মাইগ্রেশন: প্রথমে সবচেয়ে জটিল Provider-গুলিকে Bloc দিয়ে প্রতিস্থাপন করুন, তারপর বাকিগুলি। BlocProvider Provider ট্রির সাথে সামঞ্জস্যপূর্ণ: পুরানো উইজেট Provider ব্যবহার করতে পারে, নতুনগুলি — BlocProvider, একই অ্যাপ্লিকেশনের মধ্যে।
সচরাচর জিজ্ঞাসিত প্রশ্ন
BLoC বিজনেস লজিক আইসোলেশন এবং স্ট্রং টাইপিংয়ের জন্য Event + Stream ব্যবহার করে। Provider সহজ ডিপেন্ডেন্সি ইনজেকশন এবং ChangeNotifier-এর জন্য InheritedWidget-এর চারপাশে একটি র্যাপার। একাধিক অবস্থা সহ জটিল পরিস্থিতির জন্য BLoC ভাল, Provider — স্থানীয় UI অবস্থার জন্য। BLoC-তে বেশি boilerplate প্রয়োজন কিন্তু Event-এর মাধ্যমে সম্পূর্ণ ট্রেসেবিলিটি প্রদান করে।
Hydrated Bloc hydrated_bloc প্যাকেজের একটি এক্সটেনশন যা স্বয়ংক্রিয়ভাবে শেষ Stateটি লোকাল স্টোরেজে (ডিফল্টরূপে Hive) সংরক্ষণ করে। অ্যাপ্লিকেশন পুনরায় চালু হলে, Bloc প্রাথমিক অবস্থার পরিবর্তে সংরক্ষিত অবস্থা পুনরুদ্ধার করে। এটি ম্যানুয়াল সেভ কল ছাড়াই পার্সিস্টেন্স সমস্যার সমাধান করে: লগইন, কার্ট, সেটিংস সেশনের মধ্যে স্বয়ংক্রিয়ভাবে সংরক্ষিত হয়।
BLoC-এ একটি ত্রুটি mapEventToState বা on<Event>-এর ভিতরে try-catch-এর মাধ্যমে পরিচালনা করা হয়। ত্রুটিতে, Bloc একটি ত্রুটি State ফেরত দেয়: yield LoadError(error.message)। UI-তে, BlocListener বা BlocConsumer ত্রুটির ধরণের জন্য State পরীক্ষা করে এবং একটি SnackBar বা ডায়ালগ দেখায়। BlocObserver বৈশ্বিকভাবে সমস্ত অনিয়ন্ত্রিত ব্যতিক্রম লগ করে।
BLoC একটি Flutter-নির্দিষ্ট প্যাটার্ন কারণ এটি Dart Stream এবং Flutter উইজেট ব্যবহার করে। Event → Bloc → State ধারণাটি AngularDart এবং Server-side Dart-এর জন্য অভিযোজিত হতে পারে, তবে মূল ইকোসিস্টেম (BlocProvider, BlocBuilder, BlocObserver) Flutter-এর সাথে আবদ্ধ। React Native-এর জন্য Redux বা MobX ব্যবহার করুন; SwiftUI-এর জন্য Combine + MVVM ব্যবহার করুন।
Cubit — সাধারণ অবস্থার জন্য (কাউন্টার, টগল, 2-3 ফিল্ডের ফর্ম)। Bloc — জটিল লজিকের জন্য (নিউজ ফিড, অর্ডার প্রসেসিং, অনুমোদন)। মূল নিয়ম: যদি আপনার অ্যানালিটিক্স বা ডিবাগিংয়ের জন্য প্রতিটি অ্যাকশনের (Event) ট্রেসিং প্রয়োজন — Bloc বেছে নিন। যদি অবস্থা পরিবর্তনকারী মেথডগুলি যথেষ্ট — Cubit বেছে নিন। উভয় প্যাটার্ন একই প্রজেক্টে সহাবস্থান করতে পারে।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।