Bloc olayları Widget'ın dışında nasıl gönderilir?
Bloc mimarisinde yeniyim ve son zamanlarda bazı eğitimler izledim. StatelessWidget olan sayfam var ve içinde Bloc'u arayüzüm içinde başlatmak için BlocProvider kullanıyorum. Durum değişikliklerine göre farklı widget'lar döndürecektir.
Ancak öğreticilerde bile yalnızca diğer Widget'lardan (örneğin Düğmeye basarak) olayları gönderdiler. Ama benim durumumda Bloc Event'te bulunan Widget'ın dışında init API çağrısını çağırmam gerekiyor.
Eğer başka bir Widget'ın içindeysem arayabilirim BlocProvider.of<FirstTabBloc>(context).dispatch(GetUserProfile());
ama onu main () içinde arayamıyorum çünkü içerik Widget'tan değil.
Kod:
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,
);
}
},
),
],
),
],
),
)));
}
}
Yanıtlar
Bloğu elde etmek için başka bir yol kullanmanız gerekiyor.
BlocProvider.of(context)
Provider
kaputun altında kullanır . Sağlayıcı , sarmalayan bir flutter paketidir InheritedWidget
. InheritedWidget , verileri bağlam yoluyla pencere öğesi ağacından geçiren flutter widget'tır.
Yani başka bir yola ihtiyacınız var. Örneğin get_it kitaplığını kullanabilirsiniz . Dart uygulaması Service Locator
.
Widget'ın dışındaki bloğun basit bir örneği
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'));
}
}
}
Bloğunuzu get_it'e kaydedin. Ve bundan sonra onu alabilir ve bağlam olmadan kullanabilirsiniz.