Flutter BLoC 8.0.0. 没有正确发出新状态。

huangapple go评论63阅读模式
英文:

Flutter BLoC 8.0.0. not emiting new state properly

问题

我已经为您翻译了代码部分,以下是翻译好的内容:

我在Flutter中创建了一个处理UI事件的BLoC8.0.0)。我有一个ToggleButtons小部件,用户可以在三个按钮之间切换,当前选中的按钮将从数据库返回一组实体,然后在屏幕上显示这些实体。这些实体具有`bool isSale`和`bool isClosed`等其他参数,按下每个按钮应告诉BLoC搜索数据库以查找具有不同这些布尔值组合的实体,即:

1 - isSale = true,isClosed = false
2 - isSale = true,isClosed = true
3 - isSale = false,isClosed = false

我认为错误一定在我即将发布的代码中。

我创建了如下的状态:

```dart
abstract class DocViewerState extends Equatable {
  const DocViewerState();
}

class DocViewerLoadingState extends DocViewerState {
  @override
  List<Object> get props => [];
}

class DocViewerLoadedState extends DocViewerState {
  bool isSale;
  bool isClosed;
  int? selectedIndex;

  DocViewerLoadedState({required this.isSale, required this.isClosed, required this.selectedIndex});
  @override
  List<Object> get props => [isSale, isClosed];
}

用于触发此功能的事件如下:

abstract class DocViewerEvent extends Equatable {
  const DocViewerEvent();
}

class ModeChangedEvent extends DocViewerEvent {
  bool isSale;
  bool isClosed;

  ModeChangedEvent({required this.isSale, required this.isClosed});
  @override
  List<Object?> get props => [isSale, isClosed];
}

我已设置一个事件处理程序来更改搜索模式,其函数如下:

void _onModeChanged(ModeChangedEvent event, Emitter<DocViewerState> emit) {
    emit(DocViewerLoadingState());
    this.isSale = event.isSale;
    this.isClosed = event.isClosed; // 这里是因为函数外部的搜索流
    try {
      emit(DocViewerLoadedState(
        isClosed: event.isClosed,
        isSale: event.isSale,
        selectedIndex: null,
      )); // 这个发射只适用于第一和第三种组合
    } catch (e) {
      print(e); /// 我尝试把这个放在这里,因为我以为可能有一些悄无声息的异常。
                /// 没有异常。
    }
    print(event.isSale); // 这些用于打印结果,下面有描述。
    print(event.isClosed);
    print(state);
  }

我再次检查了我是否在状态和事件中使用了Equatable。我还尝试设置了上面的try catch代码。以下是在发射后的打印结果:

第一种组合 (

I/flutter (5019): true
I/flutter (5019): false
I/flutter (5019): DocViewerLoadedState(true, false)

第二种组合

I/flutter (5019): true
I/flutter (5019): true
I/flutter (5019): DocViewerLoadingState()

第三种组合

I/flutter (5019): false
I/flutter (5019): false
I/flutter (5019): DocViewerLoadedState(false, false)

如您所见,新状态没有更新,尽管参数传递正确。我应该怎么做才能使它按预期工作?

英文:

I have created a BLoC (8.0.0) in Flutter that handles events in the UI. I have a ToggleButtons widget where the user toggles between three buttons and whichever one is currently selected, returns a list of entities from the database which are then displayed on the screen. These are entities that have, among other parameters, the bool isSale and bool isClosed, and pressing each of the buttons should tell BLoC to search the database for entities with a different combination of these booleans, namely:

1 - isSale = true, isClosed = false
2 - isSale = true, isClosed = true 
3 - isSale = false, isClosed = false

I think the error must be somewhere in the code I'm going to post.

I have created states as follows:

abstract class DocViewerState extends Equatable {
  const DocViewerState();
}

class DocViewerLoadingState extends DocViewerState {
  @override
  List&lt;Object&gt; get props =&gt; [];
}

class DocViewerLoadedState extends DocViewerState {
  bool isSale;
  bool isClosed;
  int? selectedIndex;

  DocViewerLoadedState({required this.isSale, required this.isClosed, required this.selectedIndex});
  @override
  List&lt;Object&gt; get props =&gt; [isSale, isClosed];
}

The event I use to trigger this function looks like this:

abstract class DocViewerEvent extends Equatable {
  const DocViewerEvent();
}

class ModeChangedEvent extends DocViewerEvent {
  bool isSale;
  bool isClosed;

  ModeChangedEvent({required this.isSale, required this.isClosed});
  @override
  List&lt;Object?&gt; get props =&gt; [isSale, isClosed];
}

I have set up an event handler to change the search mode, the function of which looks like this:

  void _onModeChanged(ModeChangedEvent event, Emitter&lt;DocViewerState&gt; emit) {
    emit(DocViewerLoadingState());
    this.isSale = event.isSale;
    this.isClosed = event.isClosed; // This is here because of the search stream outside of this function
    try {
      emit(DocViewerLoadedState(
        isClosed: event.isClosed,
        isSale: event.isSale,
        selectedIndex: null,
      )); // This emit works only for the first and third combination
    } catch (e) {
      print(e); /// I tried to put this here because I thought maybe there is some silent exception. 
                /// There is none.
    }
    print(event.isSale); // These are for printing the results, they are described below.
    print(event.isClosed);
    print(state);
  }

I double checked that I'm using Equatable for the states and event. I also tried setting up the try catch code that is above. These are results of prints below emitting:

1st combination (

I/flutter ( 5019): true
I/flutter ( 5019): false
I/flutter ( 5019): DocViewerLoadedState(true, false)

2nd combination

I/flutter ( 5019): true
I/flutter ( 5019): true
I/flutter ( 5019): DocViewerLoadingState()

3rd combination

I/flutter ( 5019): false
I/flutter ( 5019): false
I/flutter ( 5019): DocViewerLoadedState(false, false)

As you can see, the new state isn't updating although the parameters are passed correctly. What can I do to make it work as it should?

答案1

得分: 1

我找到了解决方案。由于某种原因,参数 isClosed 似乎是某种关键字。将上面所有出现的 isClosed 重命名为 closed 突然使发射工作正常。

英文:

I found the solution. For some reason, parameter isClosed seems to be some kind of keyword. Renaming isClosed to closed in all instances where it's used above suddenly made the emiting work.

答案2

得分: 0

这只是一个非常猜测的想法,但可能是竞态条件。您可以将方法设为async,然后在打印状态之前添加延迟。

另外,我通常使用Bloc Observer来监视状态变化:

class _DebugBlocObserver extends BlocObserver {
  @override
  void onChange(BlocBase<dynamic> bloc, Change<dynamic> change) {
    super.onChange(bloc, change);
    log('onChange(${bloc.runtimeType}, $change)');
  }

  @override
  void onError(BlocBase<dynamic> bloc, Object error, StackTrace stackTrace) {
    log('onError(${bloc.runtimeType}, $error, $stackTrace)');
    super.onError(bloc, error, stackTrace);
  }
}

然后,在启动应用程序时注册此观察者:

Bloc.observer = _DebugBlocObserver();

这将打印出所有状态变化。详细文档请参考:https://bloclibrary.dev/#/fluttercountertutorial?id=blocobserver

英文:

This is just a very wild guess, but it might be a race condition. Can you make the method async and add a delay before printing out the state?

Also, what I usually do is to use a Bloc Observer to monitor state changes:

class _DebugBlocObserver extends BlocObserver {
  @override
  void onChange(BlocBase&lt;dynamic&gt; bloc, Change&lt;dynamic&gt; change) {
    super.onChange(bloc, change);
    log(&#39;onChange(${bloc.runtimeType}, $change)&#39;);
  }

  @override
  void onError(BlocBase&lt;dynamic&gt; bloc, Object error, StackTrace stackTrace) {
    log(&#39;onError(${bloc.runtimeType}, $error, $stackTrace)&#39;);
    super.onError(bloc, error, stackTrace);
  }
}

You can then register this observer when starting your app:

Bloc.observer = _DebugBlocObserver();

This prints out all state changes.

Here is the documentation: https://bloclibrary.dev/#/fluttercountertutorial?id=blocobserver

huangapple
  • 本文由 发表于 2023年3月31日 18:02:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/75897216.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定