冻结的 BLoC - 产量不会向小部件发出状态更改

Posted

技术标签:

【中文标题】冻结的 BLoC - 产量不会向小部件发出状态更改【英文标题】:BLoC with freezed - yield does not emit state change to widget 【发布时间】:2021-10-22 04:20:08 【问题描述】:

通过状态更改观察器,我可以看到我的集团将其状态更改为 LoadInProgress 并返回到 PmLoadSuccess。但是,更改为LoadInProgress 时不会调用小部件。我在BlocBuilder 中有一个断点,但是,只有在发出PmLoadSuccess 时,代码才会停在那里。

我的状态定义

@freezed
class ProblemManagerState with _$ProblemManagerState 
  const factory ProblemManagerState.initial() = PmInitial;
  const factory ProblemManagerState.loadInProgress() = PmLoadInProgress;
  const factory ProblemManagerState.loadSuccess(
      Problem problem) = PmLoadSuccess;
      ) = PmSyncFailed;

集团

@injectable
class ProblemManagerBloc extends Bloc<ProblemManagerEvent, ProblemManagerState> 
  final IProblemsRepository problemsRepository;
  ProblemManagerBloc(this.problemsRepository) : super(PmInitial());

  @override
  Stream<ProblemManagerState> mapEventToState(
    ProblemManagerEvent event,
  ) async* 
    yield PmLoadInProgress();  // <<< does not emit to widget 
    yield* event.map(
      pmProblemRequested: (e) async* 
        yield ProblemManagerState.loadInProgress();  // <<< doesn't emit either 
        print (state);
        yield* _mapPmProblemRequestedToState(e);
      ,
    );
  

  Stream<ProblemManagerState> _mapPmProblemRequestedToState(/*PmProblemRequested*/dynamic event) async* 
    dynamic nextProblem;
    late int problemClassId;
    problemClassId = event.problemClassId!;
    
    final String rootId = await _getNextProblemRootId(problemClassId);
    final Either<StorageFailure, Problem> failureOrProblem = await problemsRepository.getProblem(rootId);
    yield failureOrProblem.fold(
            (fail) => PmLoadFailure(fail),
            (load) => PmLoadSuccess(load)); // <<< yield does emit to  widget
  

小部件(如果加载成功则调用另一个小部件)

class ProblemManagerPage extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return BlocBuilder<ProblemManagerBloc, ProblemManagerState>(
        builder: (context, state) 
          return state.map(  // <<< breakpoint not reached with PmLoadInProgress (=ProblemManagerState.loadInProgress)
              initial: (_) => Container(),
              loadInProgress: (_) => const Center(
                  child: CircularProgressIndicator(),
              ),
              loadSuccess: (state) => PmGateway(state.problem),
          );
        
    );
  

【问题讨论】:

你见过这个吗? ***.com/questions/55503807/… 是的,但那是关于 Equatable 的。我正在使用 freezed ,并且没有覆盖道具(我知道)。我已经关注了 Reso Coder github.com/ResoCoder/finished-flutter-firebase-ddd-course/blob/… 的 DDD 教程 我已将其从冻结更改为 Equatable。没有变化......这可能是因为这个 bloc 的 BlocBuilder 没有直接渲染任何东西,并且因为 Widget PmGateway 调用的 Widget(在上面的 sn-p 中看到)有它自己的 bloc,它不会发出新的状态?我期待如果根块发出一个不使用其块重建子小部件的新状态,那么子小部件就会消失。 【参考方案1】:

取自github issue list

这是意料之中的,因为 BlocBuilder 只能以 60fps 的速度重建。在这种情况下,您发出状态的速度比 BlocBuilder 重建的速度要快。

【讨论】:

以上是关于冻结的 BLoC - 产量不会向小部件发出状态更改的主要内容,如果未能解决你的问题,请参考以下文章

Flutter bloc emmitInOrder 不会发出初始状态,但会发出

Flutter BLoC - 状态不会触发小部件重建

Flutter Bloc 不会改变 TextFormField 的初始值

Flutter Bloc 状态管理

如何使用 bloc flutter 更改单个列表项的状态?

Flutter 状态管理(BloC):无状态与有状态小部件