Christopher Armstrong
Christopher Armstrong

Reputation: 3557

flutter_bloc - how can i get value without BlocBuilder?

I'm still a beginner with streams and bloc pattern.

I would like to do following:

All examples are showing, how an object can be displayed in a widget with BlocBuilder. But I don't need to display the value, only get it and store it. I can't figure out how to get the value into a variable.

How can I do that? In the View class I'm dispatching the event, but now I need to know how to get the object in the state back without using BlocBuilder.

Here are the details:

Bloc

class SchoolBloc extends Bloc<SchoolEvent, SchoolState> {
  final SchoolRepository _schoolRepository;
  StreamSubscription _schoolSubscription;

  SchoolBloc({@required SchoolRepository schoolRepository})
      : assert(schoolRepository != null),
        _schoolRepository = schoolRepository;

  @override
  SchoolState get initialState => SchoolsLoading();

  @override
  Stream<SchoolState> mapEventToState(SchoolEvent event) async* {
    if (event is LoadSchool) {
      yield* _mapLoadSchoolToState();

  Stream<SchoolState> _mapLoadSchoolToState(LoadSchool event) async* {
    _schoolSubscription?.cancel();
    _schoolSubscription = _schoolRepository.school(event.id).listen(
      (school) {
        SchoolLoaded(school);
      }
    );
  }

Event

@immutable
abstract class SchoolEvent extends Equatable {
  SchoolEvent([List props = const []]) : super(props);
}
class LoadSchool extends SchoolEvent {
  final String id;

  LoadSchool(this.id) : super([id]);

  @override
  String toString() => 'LoadSchool';
}

State

@immutable
abstract class SchoolState extends Equatable {
  SchoolState([List props = const []]) : super(props);
}

class SchoolLoaded extends SchoolState {
  final School school;

  SchoolLoaded([this.school]) : super([school]);

  @override
  String toString() => 'SchoolLoaded { school: $school}';
}

View

class CourseView extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _CourseViewState();
}

class _CourseViewState extends State<CourseView> {
  @override
  initState() {
    super.initState();
    print("this is my init text");

    final _schoolBloc = BlocProvider.of<SchoolBloc>(context);

    _schoolBloc.dispatch(LoadSchool("3kRHuyk20UggHwm4wrUI"));

    // Here I want to get back the school object and save it to a db
  }

Test that fails

For testing purposes I have done following:

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:teach_mob/core/blocs/school/school.dart';

class CourseView extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _CourseViewState();
}

class _CourseViewState extends State<CourseView> {

  @override
  void initState() {
    super.initState();  
        BlocProvider.of<SchoolBloc>(context)
      .dispatch(LoadSchool("3kRHuyk20UggHwm4wrUI"));  
  }

  @override
  Widget build(BuildContext context) {
    return BlocListener<SchoolBloc, SchoolState>(
      listener: (context, state) {
        print("BlocListener is triggered");
      },
      child: Text("This is a test")
    );
  }
}

The LoadSchool event is triggered. The text in the child attribute of BlocListener is displayed, but the listener function that should print "BlocListener is triggered" is not executed.

Upvotes: 1

Views: 6132

Answers (1)

Martyns
Martyns

Reputation: 3875

Use BlocListener. It is meant to be used for those cases you mention.

Upvotes: 4

Related Questions