ryandra
ryandra

Reputation: 340

Emit to the two different state in one stream flutter bloc

I want to emit to the two different state in one stream, but first emit didn't trigger, directly trigger the second emit.

I have tried hold it using Future.delayed, but it still doesn't work, bloc automatically pass the first emit and trigger the second emit (i know it when check it in debug mode)

on<AnEvent>((event, emit) async {
  emit(somethingState1());
  await Future.delayed(const Duration(milliseconds: 5));
  emit(somethingState2());
}

My conclusions based on answers below:

  1. Use emit.foreach. I don't know how to use it. It needs stream parameter, but where the stream?. If i must create first, how? i just know event, bloc, and state.

  2. Use BlocListener. Both states is received, but if i use bloclistener, when receive state, the widget doesn't auto update. Auto update just works when use blocbuilder.

  3. Maybe multiple emit working in flutter cubit, not in flutter bloc.

So, there isn't any method to emit 2 states in 1 stream. I use not efficient way, using 2 stream and 2 state. Trigger the first stream, after receive first state, then trigger second stream, and receive second state.

Upvotes: 2

Views: 2172

Answers (3)

Md. Yeasin Sheikh
Md. Yeasin Sheikh

Reputation: 63749

Emitter provides .forEach method that can be used to emit multiple state. There will be some business logic in stream.

on<Add>((event, emit) async {
  Stream<int> stream = Stream.periodic(const Duration(seconds: 1), (i) => i);//your stream
  await emit.forEach(
    stream,
    onData: (data) {
      // dont need to wrap with `emit`,onData expect State in return
      if(data.isEven) StateA();      
      else StateB();
    },//it also provides  onError
  );
});

Upvotes: 0

Andrei
Andrei

Reputation: 44

The states update too fast and the app doesn't have time to listen to the first one because immediatelly the second one is triggerd. You can put even a smaller delay i think and it won't really affect the app, but will help you with what you want to achieve

Upvotes: 0

Nguyen family
Nguyen family

Reputation: 1048

You are misunderstanding how the stream and bloc working.

  • Imagine you have a pistol, the barrel is stream and each bullet is a state.
  • You pull the trigger first time, you emit(someState1).
  • You pull the trigger second time, you emit(someState2).
  • The period between 2 actions above, is how your your bullet was impacted, explodes, and ejected out of barrel = your business logic. It could be await Future.delayed(), it could be await http.callLoginRequest(), it could be anything.

Action "pull the trigger", or emit(someStateXX) is JUST AN ACTION to tell your UI shows loading widget or success/fail dialog or anything.

Back to your question:

  • emit(somethingState1());: Tell your UI shows loading widget.
  • await doSomething(): Do some logic here, like you said: "checked already send and arrive".
  • emit(somethingState2());: After logic completed, tell UI to update success/fail dialog.

If you don't use await Future.delayed(), or await doSomething(), it just like you are using a machine gun. 2 bullets were injected out of barrel almost immediately makes us feel 2 bullets come through at the same time. In your Flutter, it may be happens in micro-seconds and cause to our misunderstanding.

Upvotes: 2

Related Questions