I am trying to create a BLOC which depends on two other time based bloc and a non-time based bloc. What i mean with time based is, for example they are connecting a remote server so it takes time. It's working just like this:

Login (It's of course taking some time)

If login is successful

Do another process (This is something takes time also. It returns a future.)

After login and another process finishes, let the page know it.

My BLOC depends on these three:

final UserBloc _userBloc;
final AnotherBloc _anotherBloc;
final FinishBloc _finishBloc;

Inside the map event to state method I should dispatch relevant events. However i cannot await if they are finished.

_userBloc.dispatch(
  Login(),
);

_anotherBloc.dispatch(
  AnotherProcess(),
);

//LetThePageKnowIt should work after login and another process
_finishBloc.dispatch(
  LetThePageKnowIt(),
);

Is there a clean way to await some others before dispatching something?

Right know I use a way that i don't like. In the main bloc's state which i connect other blocs in it, I have bools.

class CombinerState {
  bool isLoginFinished = false;
  bool isAnotherProcessFinished = false;

I am listening the time dependent blocs' states in constructor of main bloc. When they yield "i am finished" I just mark the bools "true".

MainBloc(
  this._userBloc,
  this._anotherBloc,
  this._pageBloc,
); {
  _userBloc.state.listen(
    (state) {
      if (state.status == Status.finished) {
        dispatch(FinishLogin());
      }
    },
  );

  _anotherBloc.state.listen(
    (state) {
      if (state.status == AnotherStatus.finished) {
        dispatch(FinishAnotherProcess());
      }
    },
  );
}

and I dispatch another event for main bloc to check if all the bools are true after setting a bool to true.

else if (event is FinishAnotherProcess) {
  newState.isAnotherProcessFinished = true;

  yield newState;

  dispatch(CheckIfReady());
}

If the bools are true, i dispatch LetThePageKnowIt()

else if (event is CheckIfReady) {
  if (currentState.isAnotherProcessFinished == true &&
      currentState.isLoginFinished == true) {
    _pageBloc.dispatch(LetThePageKnowIt());
  }
}

I am not satisfied with this code. I am looking a way to await other BLOCs send a state with "finished". After that I want to dispatch my LetThePageKnowIt()


Solution 1: Mansur

@pskink 's suggestion solved my problem.

I have created two methods which return a future. Inside of them, I just await for my streams. Here is the example of login stream.

In map event to state, after the dispatches, I await an async method.

_userBloc.dispatch(
  Login(),
);

_anotherBloc.dispatch(
  AnotherProcess(),
);

await loginProcess();
await otherProcess();

_finishBloc.dispatch(
  LetThePageKnowIt(),
);

Inside the method I just await for userbloc to finish its job and yields about it. Then return.

Future loginProcess() async {
  await for (var result in _userBloc.state) {
    if (result.status == Status.finished) {
      return;
    }
  }
}