BlocBuilder在cubit emit后没有更新

18

更新 找到了onChange覆盖方法后,似乎更新的状态没有被发出 #困惑

更新2 进一步调试显示,当尝试发出更新的状态时,StreamController似乎已关闭。

出于某种原因,我的应用程序中有一个BlocBuilder在Cubit发出之后拒绝重新绘制,我无论如何都无法弄清原因,在运行或调试时没有错误,状态数据正在更新并传递到emit中。

目前,它是一个挂钩小部件,但我已经尝试将其设置为Stateless、Stateful,在effect中调用cubit方法、在context.bloc上调用等。

我尝试将其设置为consumer,但什么也没进入listen,甚至尝试过messing with listenWhen和buildWhen,但没有任何迹象表明这个widget为什么不会构建。

它呈现出加载状态,那就是它的终点。

Widget:

class LandingView extends HookWidget {
  @override
  Widget build(BuildContext context) {
    final hasError = useState<bool>(false);

    return Scaffold(
      key: const Key(LANDING_VIEW_KEY),
      body: BlocProvider<CoreCubit>(
        create: (_) => sl<CoreCubit>()..fetchDomainOptions(),
        child: BlocBuilder<CoreCubit, CoreState>(
          builder: (context, state) {
            switch (state.status) {
              case CoreStatus.loaded:
                return LandingViewLoaded();
              case CoreStatus.error:
                return LandingViewError();
              case CoreStatus.loading:
              default:
                return AppIcon();
            }
          },
        ),
      ),
    );
  }
}

立方体法:

  Future<void> fetchDomainOptions() async {
    final inputEither = await getDomainOptions();

    return inputEither.fold(
      _handleFailure,
      (options) {
        emit(state.copyWith(
          domainOptions: options,
          status: CoreStatus.loaded,
        ));
      },
    );
  }

我有几个其他的小部件,它们使用冻结的数据类工作,并且使用相同的状态键逻辑而没有任何问题,我甚至试图将一个lastUpdated时间戳键添加到它上面以进行更多数据更改,但在初始状态下,domainOptions为null,status为CoreStatus.loading,这应该已经足以触发UI更新。

TIA


你解决了这个问题吗?对我来说,即使我发出状态,它仍然保持旧状态。对我来说,我正在重新获取列表。第一次,它运行良好,但当我重新获取列表时,我发出一个加载状态,但在发出加载状态后,我看到已加载的状态(来自上一次获取)。 - Pushpendra
@Pushpendra 试着转换为有状态小部件。 - K.Amanov
对我来说,我正在覆盖重写状态的相等运算符,并且我正在发出与旧状态相同的状态。 - Pushpendra
你好,你解决了这个问题吗?我也遇到了同样的问题,在第二页获取了新数据但是无法更新第一页的内容。 - ff .n
有关此事有任何更新吗?我也是。 - joelgate
2个回答

10

我还没有弄清楚为什么会发生这种情况,但我认为我们正在处理某种竞争条件。 此外,我不知道正确的解决方法是什么,但我发现延迟调用 emit() 一段时间可以防止出现此问题。

void load() async {
  try {
    emit(LoadingState());
    final vats = await provider.all();
    await Future<void>.delayed(const Duration(milliseconds: 50));
    emit(LoadedState(vats));
  } catch (e) {
    print(e.toString());
    emit(ErrorState());
  }
}

在发出新状态之前添加 await Future<void>.delayed(const Duration(milliseconds: [需要的毫秒数]));

在 cubit 的 GitHub 上阅读有关此问题的信息后,我得出了这个结论:CubitBuilder 未接收到已发出的状态


谢谢,然而那并没有解决问题,但是让我找到了onChange覆盖方法,这表明状态实际上并没有发出。这将是一个有趣的问题,需要解决为什么。 - RemeJuan
1
这对我也解决了问题。需要硬编码延迟才能使 emit 正常工作,这太靠谱了 - 我对 BLoc 感到非常失望...尽管如此,我现在会采用这种方法。 - kris

-2

我解决了我的问题,原来是因为我使用了getIt。 我添加了参数bloc。 我的问题是没有接收到cubit(bloc)的事件(emit)。

child: BlocBuilder<CoreCubit, CoreState>(
  bloc: getIt<CoreCubit>(), // <- this
  builder: (context, state) {},
),

将GetIt与Bloc结合起来似乎不是最佳解决方案,但它可以运行。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接