تعرف على تقنية Bloc واهميتها وكيفية استخدامها في flutter
تعد تقنية البلوك واحده من تقنيات الflutter القوية والتي تسمح لنا بالبدء ببناء الصفحة او عمل تحديث لها في كل مره نستدعيها عكس استخدام setState والتي تقوم بتنفيذ الكود المراد دون الحاجه الى تحديث الصفحة وايضا الsetState تحتاج الى StatefullWidget لكي تستطيع استخدامها عكس Bloc , ايضا البلوك يمكنك من حرية بشكل اعم من الstate .
تقنية flutter واحده من التقنيات الحديثة التي احدثت ضجة كبيره في مجال ال software بسبب دعمها لاكثر من platform بكود واحد وأصبح الاقبال عليها كبير جدا ومازال العدد في زيادة وفي طبيعة الحال لابد لنا من تقديم كل جديد في مجال البرمجيات لكم بشكل مجاني بالكامل و هذا ما نسعى له وهو توفير كل ما يحتاجه المبرمجه بالمجان لكي يتمكن من تصميم وبرمجة تطبيقاته .
تعد تقنية flutter والتي تعمل بلغة Dart التي ظهرت في عام 2011 ولكن لم يكن الاقبال عليها كبير الا من بعد ظهور فلاتر في أواخر سنة ٢٠١٧ وكانت جوجل تسعى وقتها لتوحيد لغة برمجية واحده تمكن المطور من انشاء واخراج تطببق android , ios بكود واحد فقط دون الحاجه الى كتابة اكثر من كود وتعلم اكثر لغة برمجة من اجل تطوير وتصدير التطبيق .
المكتبات اللازمه لتعريف الbloc داخل pubspec
bloc: ^7.2.1
flutter_bloc: ^7.3.0
متطلبات انشاء bloc داخل Flutter
نحتاج اولا الى إنشاء ملف cubit والاخر state واذا كنت تريد تتبع حركة التطبيق يمكنك عمل observer لتتمكن من تتبع حركة التطبيق خطوة بخطوه خلال العمل ولكن هذا الملف ليس بالضروري
محتويات states class في فلاتر
هذا الملف يحتوي على اسماء للعناصر التي تريد استخدمها وعمل عملية عليها وهنا قمنا بعمل Initial وهي تكون رئيسيه لعمل التطبيق واخرى للزيادة والنقصان .
abstract class CounterState {}
class CounterInitialState extends CounterState {}
class CounterPlusState extends CounterState {}
class CounterMinusState extends CounterState {}
محتويات cubit class داخل Flutter
في هذا الملف يكون الكود الذي نكتبه وعلينا في البداية عمل super للclass وايضا اخذ context , بعدها ابدء بكتابة كودك وعند الانتهاء قم بعمل emit لكي يتمكن من تنفيذ الوظيفة بشكل صحيح وبداخلها اكتب الاسم الذي ترغب به او بمعنى اخر احجز له مكان للعمل في ملف states .
// انشاء كلاس لل Cubit والوراثه من كلاس state
class CounterCubit extends Cubit <CounterState> {
// وضع كلاس الانشاء داخل سوبر
CounterCubit () : super(CounterInitialState());
// يسهل التعامل في عدة اماكن
static CounterCubit get(context) => BlocProvider.of(context);
// التغيرات
int counter = 1;
void minus () {
counter-- ;
emit(CounterMinusState());
}
void pluse () {
counter++ ;
emit(CounterPlusState());
}
}
استدعاء الBloc داخل الclass وتعريف المتغيرات بداخله
في هذا الملف تقوم بتحويل التصميم الخاص بك اولا الى BlocProvider ويكون الcreate عباره عن cubit الخاص بك وبعدها اجعله BlocConsumer ويحتوي على الcubit و states و listener يكون عباره عن context , state والbuilder يكون ايضا عبارة عن context , state ولكن مع ارجاع التصميم الخاص بك , عند اي عملية تحتاج الى استدعاء الcubit وتقوم بأخذ قيمة العنصر او التاثير منها داخل التصميم كما يظهر بالصورة .
counter.dart
class Counter extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (BuildContext context) => CounterCubit(),
child: BlocConsumer <CounterCubit , CounterState> (
listener: (context , state) {},
builder: (context , state) {
return Scaffold(
appBar: AppBar(
title: Text('Counter'),
),
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: TextButton(onPressed: () {
CounterCubit.get(context).minus();
},
child: Text('Minus')),
),
Text('${CounterCubit.get(context).counter}', style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: TextButton(onPressed: () {
CounterCubit.get(context).pluse();
}, child: Text('Plus')),
),
],
),
),
);
}
),
);
}
}
محتويات ملف bloc_observer
في هذا الملف تكون المحتويات شبه ثابته ولا يوجد بها تغيير فيمكنك نسخ الكود التالي ووضعه داخل الملف bloc_observer الذي قمنا بشرحه في الاول ( وهو ملف لتتبع حركة الcubit في التطبيق ) .
bloc_observer.dart
import 'package:bloc/bloc.dart';
class MyBlocObserver extends BlocObserver {
@override
void onCreate(BlocBase bloc) {
super.onCreate(bloc);
print('onCreate -- ${bloc.runtimeType}');
}
@override
void onChange(BlocBase bloc, Change change) {
super.onChange(bloc, change);
print('onChange -- ${bloc.runtimeType}, $change');
}
@override
void onError(BlocBase bloc, Object error, StackTrace stackTrace) {
print('onError -- ${bloc.runtimeType}, $error');
super.onError(bloc, error, stackTrace);
}
@override
void onClose(BlocBase bloc) {
super.onClose(bloc);
print('onClose -- ${bloc.runtimeType}');
}
}
استدعاء MyBlocObserver داخل main لتتبع حالات الBloc خلال فترة عمل التطبيق
في النهاية انتقل الى الmain لتقوم بتشغيل ملف bloc_observer ويكون قبل تشغيل التصميم الخاص بك كما يظهر بالصورة التالية .
main.dart
void main () {
Bloc.observer = MyBlocObserver();
runApp(MyApp());
}