Bloc - 是否可以为导航堆栈中的前一页生成状态?

Bloc - Is it possible to yield states for a previous page in the navigation stack?

我有一个 BlocBuilder,它根据仪表板页面的生成状态处理构建小部件。

body: BlocBuilder<DashboardBloc, DashboardState>(
        builder: (context, state) {
          print(state);
          if (state is DashboardInitial) {
            return loadingList();
          } else if (state is DashboardEmpty) {
            return emptyList();
          } else if (state is DashboardLoaded) {
            return loadedList(context, state);
          }
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Navigator.push(
              context, MaterialPageRoute(builder: (context) => AddPage()));
        },

我希望能够导航到添加页面,填写一些文本字段,然后将事件发送到我的仪表板组,我的想法是在导航回仪表板时,我的列表将被更新。

class AddPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    TextEditingController titleController = TextEditingController();
    TextEditingController descriptionController = TextEditingController();
    return Scaffold(
      appBar: AppBar(title: Text('Add')),
      body: Container(
        padding: EdgeInsets.all(10),
        child: Column(
          children: [
            TextField(
              controller: titleController,
            ),
            TextField(
              controller: descriptionController,
            ),
            RaisedButton(onPressed: () {
              BlocProvider.of<DashboardBloc>(context)
                  .add(DashboardWorryAdded('title', 'description'));
            }),
          ],
        ),
      ),
    );
  }
}

当使用断点执行代码时,我能够看到我的状态是在 'mapeventtostate' 函数中生成的,但是我的仪表板从未使用新值重建。

这是我的 Bloc、事件和状态的代码。我的第一个想法是 Equatable 正在检测正在返回的相同状态,但是在删除 Equatable 后,我的问题仍然存在。

 @override
  Stream<DashboardState> mapEventToState(
    DashboardEvent event,
  ) async* {
    if (event is DashboardWorryAdded) {
      yield* _mapDashboardWorryAddedToState(event);
    } else if (event is DashboardLoading) {
      yield* _mapDashboardLoadingToState(event);
    } else if (event is AppStarted) {
      yield* _mapAppStartedToState(event);
    }
  }

  Stream<DashboardState> _mapAppStartedToState(AppStarted event) async* {
    List<Worry> _wList = await repo.getAllWorries();
    if (_wList.length != 0) {
      yield DashboardLoaded(worryList: _wList);
    } else {
      yield DashboardEmpty();
    }
  }

  Stream<DashboardState> _mapDashboardLoadingToState(
      DashboardLoading event) async* {
    List<Worry> _wList = await repo.getAllWorries();
    if (_wList != 0) {
      yield DashboardLoaded(worryList: _wList);
    } else {
      yield DashboardEmpty();
    }
  }

  Stream<DashboardState> _mapDashboardWorryAddedToState(
      DashboardWorryAdded event) async* {
    await repo.addWorry(event.title, event.description);
    List<Worry> worryList = List<Worry>();
    worryList = await repo.getAllWorries();
    yield DashboardLoaded(worryList: worryList);
  }
}
@immutable
abstract class DashboardEvent {}

class DashboardLoading extends DashboardEvent {
  DashboardLoading();
}

class DashboardWorryAdded extends DashboardEvent {
  final String title, description;

  DashboardWorryAdded(this.title, this.description);
}

class AppStarted extends DashboardEvent {
  AppStarted();
}
@immutable
abstract class DashboardState {}

class DashboardInitial extends DashboardState {
  DashboardInitial();
}

class DashboardLoaded extends DashboardState {
  final List<Worry> worryList;

  DashboardLoaded({this.worryList});
}

class DashboardEmpty extends DashboardState {
  DashboardEmpty();
}

与其试图改变另一个页面的状态(有点像 no-no 涉及状态管理),不如利用导航器的 push 方法 returns 当该页面弹出时完成的未来,作为奖励,未来的价值将包括在另一页中给予 pop 方法的价值。所以你现在可以这样做:

class DashboardBloc {
  ...

  void showAddPage() async {
    // Do this to retrieve the value passed to the add page's call to `pop`
    final value = await Navigator.of(context).push(...);

    // Do this if the add page doesn't return a value in `pop`
    await Navigator.of(context).push(...);

    // Either way, you can now refresh your state in response to 
    // the add page popping
    emit(...);
  }
}

注意:这也适用于命名路由。