Welcome to JiKe DevOps Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
348 views
in Technique[技术] by (71.8m points)

android - Flutter Bloc - BlocListener not reacting to state change

The idea of my app is that a user is able to add time off appointments. After adding a new time off appointment the user get a notification message. To achive this I have a time off bloc whitch reacts to the AddTimeOffEvent and set two states TimeOffAddingState and TimeOffAddedState. I am using the flutter_bloc library.

My bloc:

class TimeOffBloc extends Bloc<TimeOffEvent, TimeOffState> {
  TimeOffRepository repository;
  String activeUser;

  TimeOffBloc({@required this.repository}) : super(TimeOffInitialState());

  @override
  Stream<TimeOffState> mapEventToState(TimeOffEvent event) async* {
    if (event is AddTimeOffEvent) {
      yield TimeOffAddingState();
      try {
        var addResult = await repository.addTimeOff(event.timeOff, activeUser);
        TimeOffsRange timeOffsRange =
            await repository.fetchTimeOffRange(activeUser);
        yield TimeOffAddedState(
            timeOffs: timeOffsRange, excludedWeekends: addResult);
      } catch (e) {
        yield TimeOffErrorState(message: e.toString());
      }
    }
  }
}

My events:

abstract class TimeOffEvent extends Equatable {}

class AddTimeOffEvent extends TimeOffEvent {
  final AddTimeOff timeOff;

  AddTimeOffEvent({@required this.timeOff});

  List<Object> get props => [timeOff];
}

My states:

abstract class TimeOffState extends Equatable {}

class TimeOffInitialState extends TimeOffState {
  String message = "Loading";

  @override
  List<Object> get props => [];
}

class TimeOffAddedState extends TimeOffState {
  TimeOffsRange timeOffs;
  String excludedWeekends;

  TimeOffAddedState({@required this.timeOffs, this.excludedWeekends});

  List<Object> get props => [timeOffs, excludedWeekends];
}

class TimeOffAddingState extends TimeOffState {
  String message = "Adding new time off appointments.";

  @override
  List<Object> get props => [message];
}

class TimeOffErrorState extends TimeOffState {
  String message;

  TimeOffErrorState({@required this.message});

  @override
  List<Object> get props => [message];
}

Bloc Builder

The state change from TimeOffAddingState to TimeOffAddedState is detected in the bloc builder widget.

class _TimeOffListContainerState extends State<TimeOffListContainer> {
  TimeOffBloc timeOffBloc;

  @override
  void initState() {
    super.initState();
    timeOffBloc = BlocProvider.of<TimeOffBloc>(context);
  }

  @override
  Widget build(BuildContext context) {
    return RefreshIndicator(
      onRefresh: () => getTimeOffs(),
      child: BlocBuilder<TimeOffBloc, TimeOffState>(
        builder: (context, state) {
          if (state is TimeOffInitialState) {
            return Loading(loadingMessage: state.message);
          } else if (state is TimeOffAddingState) {
            return Loading(loadingMessage: state.message);
          } else if (state is TimeOffAddedState) {
            return TimeOffList(
                timeOffs: state.timeOffs, timeOffBloc: timeOffBloc);
          } else if (state is TimeOffErrorState) {
            return Error(
              errorMessage: state.message,
              onRetryPressed: () => getTimeOffs(),
            );
          }
        },
      ),
    );
  }
}

I have a timeOffListPage where I display the time of appointments. On the page is a Bloc Listener who should display a message on the TimeOffAddesState. But this does not work. During debugging I found out, that the BlocListener is called when the TimeOffAddingState is set. But the TimeOffAddedState gets ignored. The confusing thing is when I don't yield the TimeOffAddingState on the bloc then the bloc listener works for the TimeOffAddedState.

    final TimeOffsRange timeOffs;
  final TimeOffBloc timeOffBloc;

  const TimeOffList({Key key, this.timeOffs, this.timeOffBloc})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocListener<TimeOffBloc, TimeOffState>(
      listener: (context, state) {
        if (state is TimeOffAddedState) { //is never called...
          if (state.excludedWeekends.isNotEmpty) {
            showSimpleNotification(
              Text(state.excludedWeekends),
              background: Colors.amber,
              duration: Duration(milliseconds: 10000),
            );
          }
        }
      },
      child: Scaffold(...

Any ideas?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

Please log in or register to answer this question.

1 Answer

0 votes
by (71.8m points)

Please look into this below code, I have added comments where I inserted the new lines of code. Let me know if it helps you or not.

My bloc:

class TimeOffBloc extends Bloc<TimeOffEvent, TimeOffState> {
  TimeOffRepository repository;
  String activeUser;

  TimeOffBloc({@required this.repository}) : super(TimeOffInitialState());

  @override
  Stream<TimeOffState> mapEventToState(TimeOffEvent event) async* {
    if (event is AddTimeOffEvent) {
      yield TimeOffAddingState();
      try {
        var addResult = await repository.addTimeOff(event.timeOff, activeUser);
        TimeOffsRange timeOffsRange =
            await repository.fetchTimeOffRange(activeUser);
        //add this line of code
        yield TimeOffIdleState();
        await Future.delayed(duration: Duration(milliseconds : 20));
        yield TimeOffAddedState(
            timeOffs: timeOffsRange, excludedWeekends: addResult);
      } catch (e) {
        //add this line of code
        yield TimeOffIdleState();
        await Future.delayed(duration: Duration(milliseconds : 20));
        yield TimeOffErrorState(message: e.toString());
      }
    }
  }
}

My events:

abstract class TimeOffEvent extends Equatable {}

class AddTimeOffEvent extends TimeOffEvent {
  final AddTimeOff timeOff;

  AddTimeOffEvent({@required this.timeOff});

  List<Object> get props => [timeOff];
}

My states:

abstract class TimeOffState extends Equatable {}

class TimeOffInitialState extends TimeOffState {
  String message = "Loading";

  @override
  List<Object> get props => [];
}

class TimeOffAddedState extends TimeOffState {
  TimeOffsRange timeOffs;
  String excludedWeekends;

  TimeOffAddedState({@required this.timeOffs, this.excludedWeekends});

  List<Object> get props => [timeOffs, excludedWeekends];
}

class TimeOffAddingState extends TimeOffState {
  String message = "Adding new time off appointments.";

  @override
  List<Object> get props => [message];
}

class TimeOffErrorState extends TimeOffState {
  String message;

  TimeOffErrorState({@required this.message});

  @override
  List<Object> get props => [message];
}
//add this class
class TimeOffIdleState extends TimeOffState {
  @override
  List<Object> get props => [];
}

Bloc Builder

The state change from TimeOffAddingState to TimeOffAddedState is detected in the bloc builder widget.

class _TimeOffListContainerState extends State<TimeOffListContainer> {
  TimeOffBloc timeOffBloc;

  @override
  void initState() {
    super.initState();
    timeOffBloc = BlocProvider.of<TimeOffBloc>(context);
  }

  @override
  Widget build(BuildContext context) {
    return RefreshIndicator(
      onRefresh: () => getTimeOffs(),
      child: BlocBuilder<TimeOffBloc, TimeOffState>(
        builder: (context, state) {
          if (state is TimeOffInitialState) {
            return Loading(loadingMessage: state.message);
          } else if (state is TimeOffAddingState) {
            return Loading(loadingMessage: state.message);
          } else if (state is TimeOffAddedState) {
            return TimeOffList(
                timeOffs: state.timeOffs, timeOffBloc: timeOffBloc);
          }
            //add this line of code, you can return any widget at all
            else if (state is TimeOffIdleState){return Container();}
            else if (state is TimeOffErrorState) {
            return Error(
              errorMessage: state.message,
              onRetryPressed: () => getTimeOffs(),
            );
          }
        },
      ),
    );
  }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to JiKe DevOps Community for programmer and developer-Open, Learning and Share

Just Browsing Browsing

[5] html - How to create even cell spacing within a

755k questions

754k answers

5 comments

53.3k users

...