颤抖:尽管我在调试器中看到新的/不同的状态,但BLoC Builder无法更新

时间:2020-09-18 16:48:04

标签: flutter state bloc

我今天的第二个奇怪事件。当我在bloc.dart(库,而不是我的文件)中跟踪调试器时,发现transition.nextState == state && _emittedfalse时,它不会更新我的小部件(nextState的列表大小为2,状态为10- _emitted为true)。据我了解,构建器应该可以,为什么还有其他地方不能更新?

在我展示代码之前先解释一下逻辑

  1. 我在应用启动时获取数据

    BlocProvider(create: (context) =>
      LogicGraphsPStmntBloc(logicGraphsRepository:
      logicGraphsRepository)..add(LogicGraphsNextProblemRequested()),
    
  2. 这将返回10个字符串的列表,并将它们存储在_bloc.dart文件中(不确定这是否是最新技术)

  3. 这10个字符串通过状态LogicGraphsPStmntLoadSuccess(statements)发送,并正确地呈现为按钮

  4. 如果单击按钮,则仅显示第一个和所选的字符串。该事件已通过onPressed: () {BlocProvider.of<LogicGraphsPStmntBloc>(context).add(LogicGraphsPStmntCollapsed(statement: index-1));},

    正确触发
  5. 这会正确触发状态yield LogicGraphsPStmntLoadSuccess(statementsShown);,现在列表中仅包含2个元素(与之相比,步骤3中为10个元素),但是不会导致重新呈现

  6. 如果我使用调试器进入状态,则可以看到两种状态都有不同数量的元素。

我的状态

abstract class LogicGraphsPStmntState extends Equatable {
  const LogicGraphsPStmntState();
  @override
  List<Object> get props => [];
}

class LogicGraphsPStmntLoadSuccess extends LogicGraphsPStmntState {
  const LogicGraphsPStmntLoadSuccess([this.statements = const []]);
  final List<String> statements;

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

  @override
  String toString() => 'LogicGraphsPStmntLoadSuccess { statements: $statements }';
}

我的集团(不完全是,因为未达到my other issue中所述的子函数内部的代码来释放状态。所以目前,我在mapEventToState =

中将这些子函数行作为意大利面条
class LogicGraphsPStmntBloc extends Bloc<LogicGraphsPStmntEvent, LogicGraphsPStmntState> {
  LogicGraphsPStmntBloc({@required this.logicGraphsRepository}) : super(LogicGraphsPStmntInProgress());
  final LogicGraphsRepository logicGraphsRepository;
  List<String> statements;
  int currentProblem = -1;

  @override
  Stream<LogicGraphsPStmntState> mapEventToState(LogicGraphsPStmntEvent event) async* {
        if (event is LogicGraphsNextProblemRequested) {
          _mapLGPStmntNewProblemRequested();
          _mapLGPStmntLoadRequested(currentProblem);
        }
        else if (event is LogicGraphsPStmntLoadRequested) {
          _mapLGPStmntLoadRequested(currentProblem);
        }
        else if (event is LogicGraphsPStmntCollapsed) {
          _mapLGPStmntCollapseRequested(event);
  }
  Stream<LogicGraphsPStmntState> _mapLGPStmntNewProblemRequested() async* {
        try {
          currentProblem =
          await getNextProblem(currentProblem == null ? -1 : currentProblem);
          statements =
          await logicGraphsRepository.getProblemStmntList(currentProblem);
          _mapLGPStmntLoadRequested(currentProblem);
        } catch (_) {
          yield LogicGraphsPStmntLoadFailure();
        }
  }
  Stream<LogicGraphsPStmntState> _mapLGPStmntLoadRequested(int problem) async* {
          try {
            yield LogicGraphsPStmntLoadSuccess(statements);
          } catch (_) {
            yield LogicGraphsPStmntLoadFailure();
          }
  }
  Stream<LogicGraphsPStmntState> _mapLGPStmntCollapseRequested(
          LogicGraphsPStmntCollapsed event) async* {
          List<String> statementsShown = [];
          statementFocussed = event.statement;
          statementsShown.add(statements[0]);
          statementsShown.add(statements[statementFocussed]);
          yield LogicGraphsPStmntLoadSuccess(statementsShown);
  }
}

我的小部件

class LogicGraphPage extends StatelessWidget {
  final LogicGraphsRepository logicGraphsRepository = LogicGraphsRepository(
      logicGraphsApiClient: LogicGraphsApiClient());

  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      child: BlocProvider(
        create: (context) =>
        LogicGraphsPStmntBloc(logicGraphsRepository: logicGraphsRepository)
          ..add(LogicGraphsNextProblemRequested()),
          child:BlocBuilder<LogicGraphsPStmntBloc, LogicGraphsPStmntState>(
            builder: (context, state) {
              if (state is LogicGraphsPStmntLoadSuccess) {
                final List<String> statements = state.statements;
                return ListView.builder(
                    itemCount: statements.length,
                    itemBuilder: (BuildContext context, int index) {
                      return CupertinoButton(
                        padding: EdgeInsets.all(0),
                        child: Text(statements[index])
                        onPressed: () {BlocProvider.of<LogicGraphsPStmntBloc>(context).add(LogicGraphsPStmntCollapsed(statement: index-1));},
                      );
                    });
              }
              else return Container();
            }
        )
      ),
    );
  }
}

在bloc.dart库中的函数,我假设发出了新状态。您会看到if (transition.nextState == state && _emitted) return;行。下一个状态有2个元素,状态有10个,_emitted为true,所以我假设代码继续。而是触发返回,并跳过带有emit(transition.nextState);的行。

任何帮助都将受到高度赞赏,因为这是我第一次接触BLoC / equableable,而且颤动对我来说还是很新的。但是我正在进步!

 void _bindEventsToStates() {
    _transitionSubscription = transformTransitions(
      transformEvents(
        _eventController.stream,
            (event) => mapEventToState(event).map(
              (nextState) => Transition(
            currentState: state,
            event: event,
            nextState: nextState,
          ),
        ),
      ),
    ).listen(
          (transition) {
        if (transition.nextState == state && _emitted) return; // <<<<<<<<<<<
        try {
          onTransition(transition);
          emit(transition.nextState);
        } on dynamic catch (error, stackTrace) {
          onError(error, stackTrace);
        }
        _emitted = true;
      },
      onError: onError,
    );
  }

1 个答案:

答案 0 :(得分:2)

我想集团无法分辨LogicGraphsPStmntLoadSuccess(statements)LogicGraphsPStmntLoadSuccess(statementsShown)之间的差异,因为它们是相同的状态,并且我认为它无法发现不同参数之间的差异。

所以我建议这样做: 在产生LogicGraphsPStmntLoadSuccess(statementsShown)之前,请尝试产生“切换”状态,例如之前我不知道LogicGraphsPStmntChangeStatement。 所以:

yield LogicGraphsPStmntChangeStatement;
yield LogicGraphsPStmntLoadSuccess(statementsShown);

应该可以解决问题。