exemple_states:
abstract class ExampleState extends Equatable {
const ExampleState();
}
class LoadingState extends ExampleState {
//
}
class LoadedState extends ExampleState {
//
}
class FailedState extends ExampleState {
//
}
exemple_events:
abstract class ExampleEvent extends Equatable {
//
}
class SubscribeEvent extends ExampleEvent {
//
}
class UnsubscribeEvent extends ExampleEvent {
//
}
class FetchEvent extends ExampleEvent {
//
}
exemple_bloc:
class ExampleBloc extends Bloc<ExampleEvent, ExampleState> {
@override
ExampleState get initialState => LoadingState();
@override
Stream<ExampleState> mapEventToState(
ExampleEvent event,
) async* {
if (event is SubscribeEvent) {
//
} else if (event is UnsubscribeEvent) {
//
} else if (event is FetchEvent) {
yield LoadingState();
try {
// network calls
yield LoadedState();
} catch (_) {
yield FailedState();
}
}
}
}
exemple_screen:
class ExampleScreenState extends StatelessWidget {
// ignore: close_sinks
final blocA = ExampleBloc();
@override
Widget build(BuildContext context) {
return Scaffold(
body: BlocBuilder<ExampleBloc, ExampleState>(
bloc: blocA,
// ignore: missing_return
builder: (BuildContext context, state) {
if (state is LoadingState) {
blocA.add(Fetch());
return CircularProgressBar();
}
if (state is LoadedState) {
//...
}
if (state is FailedState) {
//...
}
},
),
);
}
}
Comme vous pouvez le constater dans Exemple_bloc, l'état initial est le chargement du chargement () et dans la construction indique une barre de progression circulaire. J'utilise l'événement Fetch () pour déclencher des états suivants. Mais je ne me sens pas à l'aise en utilisant là-bas. Ce que je veux faire, c'est:
Lorsque l'application démarre, il doit afficher le chargement de l'État et démarrer les appels de réseau, puis lorsqu'il est terminé, il devrait indiquer que LoquetState avec des résultats d'appel de réseautage et échoué si quelque chose ne va pas. Je veux y parvenir sans faire
if (state is LoadingState) {
blocA.add(Fetch());
return CircularProgressBar();
}
Votre inconfort a vraiment raison - aucun événement ne doit être tiré de build()
Méthode (Build () pourrait être tiré autant de fois que les besoins crocheurs)
Notre cas est d'incendier l'événement initial sur la création du Bloc
Possibilités d'aperçu
create:
rappel est déclenché une seule fois lorsque BlocProvider est monté et BlocProvider fermerait () Bloc lorsque BlocProvider est démontré
class ExampleScreenState extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: BlocProvider(
create: (context) => ExampleBloc()..add(Fetch()), // <-- first event,
child: BlocBuilder<ExampleBloc, ExampleState>(
builder: (BuildContext context, state) {
...
},
),
),
);
}
}
State
de widget étatiqueclass _ExampleScreenStateState extends State<ExampleScreenState> {
ExampleBloc _exampleBloc;
@override
void initState() {
super.initState();
_exampleBloc = ExampleBloc();
_exampleBloc.add(Fetch());
// or use cascade notation
// _exampleBloc = ExampleBloc()..add(Fetch());
}
@override
void dispose() {
super.dispose();
_exampleBloc.close(); // do not forget to close, prefer use BlocProvider - it would handle it for you
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: BlocBuilder<ExampleBloc, ExampleState>(
bloc: _exampleBloc,
builder: (BuildContext context, state) {
...
},
),
);
}
}
class ExampleBloc extends Bloc<ExampleEvent, ExampleState> {
...
ExampleBloc() {
add(Fetch());
}
}
// insert it to widget tree with BlocProvider or create in State
BlocProvider( create: (_) => ExampleBloc(), ...
// or in State
class _ExampleScreenStateState extends State<ExampleScreenState> {
final _exampleBloc = ExampleBloc();
...
PS N'hésitez pas à me joindre à des commentaires