首页 > 解决方案 > Bloc - 是否可以在导航堆栈中为上一页产生状态?

问题描述

我有一个 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();
}

标签: flutterdartstateblocflutter-bloc

解决方案


与其试图改变另一个页面的状态(在状态管理方面有点禁忌)push,不如利用导航器的方法返回一个在该页面弹出时完成的未来,作为奖励,未来的值将包括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(...);
  }
}

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


推荐阅读