विजेट के बाहर ब्लॉक घटनाओं को कैसे भेजें?
मैं ब्लाक आर्किटेक्चर के लिए नया हूं और मैंने हाल ही में कुछ ट्यूटोरियल देखे हैं। मेरे पास पेज है जो स्टेटलेसविजेट है और अंदर मैं अपने यूआई के अंदर ब्लाक को इनिशियलाइज़ करने के लिए ब्लाकप्रोवाइडर का उपयोग कर रहा हूं। यह राज्य परिवर्तनों के आधार पर विभिन्न विजेट लौटाएगा।
लेकिन यहां तक कि ट्यूटोरियल में भी वे अन्य विजेट्स (उदाहरण के लिए बटन दबाकर) से घटनाओं को भेजते हैं। लेकिन मेरी स्थिति में मुझे विजेट के बाहर init API कॉल करने की आवश्यकता है जो कि Bloc Event में है।
यदि मैं अन्य विजेट के अंदर हूं तो मैं कॉल कर सकता हूं BlocProvider.of<FirstTabBloc>(context).dispatch(GetUserProfile());
लेकिन मैं इसे मुख्य () में नहीं कह सकता क्योंकि संदर्भ विजेट से नहीं है।
कोड:
class FirstPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: firstTabElement(context),
),
appBar: EmptyAppBar(mainAppColor),
);
}
BlocProvider<FirstTabBloc> firstTabElement(BuildContext context) {
return BlocProvider(
builder: (_) => sl<FirstTabBloc>(),
child: Expanded(
child: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: Column(
children: <Widget>[
Stack(
children: [
//Main Background
Column(children: <Widget>[
//Top part
Container(
constraints: BoxConstraints(
minHeight: 120,
),
width: MediaQuery.of(context).size.width,
height: 300,
decoration: new BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: ticketGradient,
),
),
),
// Bottom part - white
Container(
color: basicWhite,
),
]),
//content above background
BlocBuilder<FirstTabBloc, FirstTabState>(
builder: (context, state) {
if (state is Uninitialized) {
return WalletWidget(
credit: formatPrice(0),
currency: '€',
);
} else if (state is Loading) {
return LoadingWidget();
} else if (state is Loaded) {
Wallet currWallet = state.profile.getWalletByClient(clientId);
return WalletWidget(
credit: formatPrice(currWallet.value),
currency: formatCurrency(currWallet.currency),
);
} else if (state is Error) {
return MessageDisplay(
message: state.message,
);
}
},
),
],
),
],
),
)));
}
}
जवाब
ब्लॉक प्राप्त करने के लिए आपको दूसरे तरीके का उपयोग करने की आवश्यकता है।
BlocProvider.of(context)
Provider
हुड के तहत उपयोग करता है । प्रदाता एक स्पंदन पैकेज है, जो लपेटता है InheritedWidget
। InheritedWidget स्पंदन विजेट है जो संदर्भ के माध्यम से विजेट ट्री के नीचे डेटा पास करता है।
तो आपको एक और तरीका चाहिए। उदाहरण के लिए आप get_it लाइब्रेरी का उपयोग कर सकते हैं । इसका डार्ट कार्यान्वयन है Service Locator
।
विजेट के बाहर ब्लॉक के साथ सरल उदाहरण
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
final bloc = CounterBloc();
void main() {
bloc.add(CounterEvent.increment);
bloc.add(CounterEvent.increment);
bloc.add(CounterEvent.increment);
bloc.add(CounterEvent.increment);
runApp(
MyApp(),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: SafeArea(
child: MyHomePage(),
),
),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => bloc,
child: CounterPage(),
);
}
}
class CounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Counter')),
body: BlocBuilder<CounterBloc, int>(
builder: (_, count) {
return Center(
child: Text('$count', style: Theme.of(context).textTheme.headline1),
);
},
),
floatingActionButton: Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(vertical: 5.0),
child: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () =>
context.bloc<CounterBloc>().add(CounterEvent.increment),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 5.0),
child: FloatingActionButton(
child: const Icon(Icons.remove),
onPressed: () =>
context.bloc<CounterBloc>().add(CounterEvent.decrement),
),
),
],
),
);
}
}
enum CounterEvent { increment, decrement }
class CounterBloc extends Bloc<CounterEvent, int> {
CounterBloc() : super(0);
@override
Stream<int> mapEventToState(CounterEvent event) async* {
switch (event) {
case CounterEvent.decrement:
yield state - 1;
break;
case CounterEvent.increment:
yield state + 1;
break;
default:
addError(Exception('unsupported event'));
}
}
}
अपने ब्लॉक को get_it में पंजीकृत करें। और इसके बाद आप इसे प्राप्त कर सकते हैं और संदर्भ के बिना उपयोग किया जा सकता है।