DavidGetter
DavidGetter

Reputation: 369

Flutter, using a bloc in a bloc

I have two BLoCs.

My Application basically gets estates from an API and displays them in a similar fashion

Now I wanted to add a sort functionality, but I could only access the List of Estates via a specific state.

    if(currentState is PostLoadedState){{
    print(currentState.estates);
    }

I wanted to make the List of estates available for whichever bloc, that needed that list.

What I did was, I created the EstateTryBloc, which basically contains the List of estates as a state.

class EstateTryBloc extends Bloc<EstateTryEvent, List<Estate>> {
  @override
  List<Estate> get initialState => [];

  @override
  Stream<List<Estate>> mapEventToState(
    EstateTryEvent event,
  ) async* {


    final currentState = state;
    if(event is AddToEstateList){
      final estates = await FetchFromEitherSource(currentState.length, 20)
          .getDataFromEitherSource();
      yield currentState + estates;
    }
  }
}

As I print the state inside the bloc I get the List of estates but I dont know how I would use that List in a different bloc.

print(EstateTryBloc().state);

simply shows the initialState.

I am open for every kind of answer, feel free to tell me if a different approach would be better.

Upvotes: 1

Views: 262

Answers (4)

Logachu
Logachu

Reputation: 609

Old question, but I thought it was worth putting in the advice from the docs for bloc library. This is a basic reasonable question that needs a reasonable answer.

Because blocs expose streams, it may be tempting to make a bloc which listens to another bloc. You should not do this. There are better alternatives...

Generally, sibling dependencies between two entities in the same architectural layer should be avoided at all costs, as it creates tight-coupling which is hard to maintain. Since blocs reside in the business logic architectural layer, no bloc should know about any other bloc.

...although here you are suggesting a parent-child relationship not a sibling dependency.

I think if you study those architecture docs, you'll see the list of estates as part of the domain model which belongs in a repository that exposes the list of estates to any bloc in the application layer. If you want blocs to react to any change in the estate list (as opposed to just fetching it once) then that EstateRepository could expose a Stream<List<Estate>>. Otherwise just expose a List<Estates> property or, if it takes to time to fetch estates from a database or remote data source, an async Future<List<Estates>> fetchEstates() method.

Upvotes: 1

DavidGetter
DavidGetter

Reputation: 369

To be honest I overcomplicated things a little bit and did not recognize the real problem. It was that I accidently created a new instance of EstateBloc() whenever I pressed on the sort button. Anyways, thanks for your contribution guys!

Upvotes: 0

Karol Lisiewicz
Karol Lisiewicz

Reputation: 674

Right now the recommended way to share data between blocs is to inject one bloc into another and listen for state changes. So in your case it would be something like this:

class EstateTryBloc extends Bloc<EstateTryEvent, List<Estate>> {
  final StreamSubscription _subscription;

  EstateTryBloc(EstateBloc estateBloc) {
    _subscription = estateBloc.listen((PostState state) {
      if (state is PostLoadedState) {
        print(state.estates);
      }
    });
  }

  @override
  Future<Function> close() {
    _subscription.cancel();
    return super.close();
  }
}

Upvotes: 1

Miguel Ruivo
Miguel Ruivo

Reputation: 17796

When you do print(EstateTryBloc().state); you are creating a new instance of EstateTryBloc() that's why you always see the initialState instead of the current state.

For that to work, you must access the reference for the instance that you want to get the states of. Something like:

final EstateTryBloc bloc = EstateTryBloc();

// Use the bloc wherever you want

print(bloc.state);

Upvotes: 1

Related Questions