问题
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()
回答1:
@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;
    }
  }
}
来源:https://stackoverflow.com/questions/56322631/awaiting-some-results-before-dispatching-an-event-with-flutter-bloc-library