5

I have a screen(A) which use 'AccountFetched' state to load list of data from database:

return BlocProvider<AccountBloc>(
      create: (context) {
        return _accountBloc..add(FetchAccountEvent());
      },
      child: BlocBuilder<AccountBloc, AccountState>(
        builder: (context, state) {
          if (state is AccountFetched) {
            accounts = state.accounts;
          }

And in my second screen(B) I call AddAccountEvent to add data to database and navigate back to screen(A) which is the parent screen.

onPressed: () {
   BlocProvider.of<AccountBloc>(context)
     ..add(AddAccountEvent(account: account));
   Navigator.of(context).pop();
}

But when I navigate back to screen A, the list of data is not updated. Should I refresh the screen(A) manually or how can I update the state of bloc?

This is my bloc class:

class AccountBloc extends Bloc<AccountEvent, AccountState> {
  AccountBloc() : super(AccountInitial());

  @override
  Stream<AccountState> mapEventToState(AccountEvent event) async* {
    if (event is FetchAccountEvent) yield* _fetchAccountEvent(event, state);
    if (event is AddAccountEvent) yield* _addAccountEvent(event, state);
  }

  Stream<AccountState> _fetchAccountEvent(
      FetchAccountEvent event, AccountState state) async* {
    yield FetchingAccount();
    final dbAccount = await DBAccountRepository.instance;
    List<Account> accounts = await dbAccount.accounts();
    yield AccountFetched(accounts: accounts);
  }

  Stream<AccountState> _addAccountEvent(
      AddAccountEvent event, AccountState state) async* {
    yield AddingAccount();
    final dbAccount = await DBAccountRepository.instance;
    final insertedId = await dbAccount.insertAccount(event.account);
    yield AccountAdded(insertedId: insertedId);
  }
}
noyruto88
  • 767
  • 2
  • 18
  • 40

3 Answers3

1

I was experiencing the same problem, the solution I found was to make screen A wait for screen B to close, and after that trigger the data reload event for screen A.

onTap: () async {
           await Navigator.of(context).push(ScreenB());
           _bloc.add(RequestDataEvent());
          }

So it will only execute the event after screen B is closed

0

well, you are creating a new bloc on page A. try to move BlocProvider 1 level up. so when the build function of page A calls, doesn't create a new bloc.

reza
  • 1,354
  • 1
  • 7
  • 25
-1

You should have a BlocListener in screen A listening for AccountState , with a if ( state is AccountFetched ) {} statement and perform your data update in a setState() . Depending on how long it takes to display screen A you might have the AccountFetched state been yielded before so screen A won't see it, in this case you could delay by 250 milliseconds yielding it in your _addAccount method either with a Timer or a Future.delayed. Hope it helped.

Vincenzo
  • 5,304
  • 5
  • 38
  • 96