【问题标题】:Bloc is either calling multiple times or not getting called at allBloc 要么多次调用,要么根本没有被调用
【发布时间】:2021-08-18 15:26:24
【问题描述】:

我有 2 个屏幕

  1. 屏幕A
  2. 屏幕 B

我通过以下代码从screen A 转到Screen B

    onTap: () {
      Navigator.pushNamed(context, '/screen_b');
    },

屏幕B代码

class ScreenB extends StatefulWidget {
  @override
  _ScreenBState createState() => _ScreenBState();
}

class _ScreenBState extends State<ScreenB> {

   SampleBloc sampleBloc;

    @override
    void initState() {
       super.initState();
       sampleBloc = BlocProvider.of<SampleBloc>(context);

       sampleBloc.stream.listen((state) {
          // this is getting called multiple times.
       }
    }

    @override
    void dispose() {
       super.dispose();
       sampleBloc.clear(); // If i add this, no event is firing from second time i come to the page. initState() is being called i checked so sampleBloc is not null.
    }
   
    
    @override
    Widget build(BuildContext context) {
       ....
           onTap: () {
              sampleBloc.add(CreateSampleEvent());
           },
       ....
    }

}

当我点击将CreateSampleEvent 添加到屏幕B 中的sampleBloc 时,'sampleBloc.stream.listen' 会被多次触发。

样本结果

步骤 1. 首先执行sampleBloc.add (tap) -> sampleBloc.stream.listen 被解雇一次
步骤 2. 返回屏幕 A 并返回 屏幕B 第二次去sampleBloc.add (tap) -> 在一个案例中我看到了 射击发生在一对 2 次,在其他时间 射击成对发生 4 次。

class SampleBloc extends Bloc<SampleEvent, SampleState> {
  final SampleRepository sampleRepository;

  SampleBloc({this.sampleRespository}) : super(null);


  @override
  Stream<SampleState> mapEventToState(SampleEvent event) async* {
    if (event is SampleEvent) {
      yield* mapSampleEventToState();
    }
  }

  Stream<SampleEvent> mapSampleEventToState() async* {
    yield SampleInProgressState();
    try {
      String sampleId = await sampleRepository.createSample();
      if (sampleId != null) {
        yield SampleCompletedState(sampleId, uid);
      } else {
        yield SampleFailedState();
      }
    } catch (e) {
      print('Error: $e');
      yield SampleFailedState();
    }
  }

有什么想法可能会出错吗?

【问题讨论】:

  • 你只在initState()收听吗? Aso,如果您可以发布您的SampleBloc,它会有所帮助。
  • @MiguelRuivo 是的先生。
  • @SaurabhKumar 返回屏幕 A 时是否取消了流订阅?您是否在屏幕 B 中实现了 dispose,您是否也可以添加该代码?
  • @MiguelRuivo 添加了 SampleBloc
  • @MidhunMP 你的意思是在屏幕 B 的 dispose 方法中调用 sampleBloc.clear() 吗?

标签: flutter flutter-layout flutter-bloc


【解决方案1】:

由于您正在创建手动订阅(通过获取 Bloc 然后收听stream),您还需要在完成后手动取消该订阅,否则,SampleBloc 将继续获得新订阅并为所有订阅者产生事件。

为此,您可以:

  1. 保存订阅,然后在dispose() 方法中取消订阅。
   SampleBloc sampleBloc;
   StreamSubscription _subscription;

    @override
    void initState() {
       super.initState();
       sampleBloc = BlocProvider.of<SampleBloc>(context);

       _subscription = sampleBloc.stream.listen((state) {
          // this is getting called multiple times.
       }
    }
    
   @override
   void dispose() {
     _subscription.cancel();
     super.dispose();
   }
  1. 您可以利用包中的BlocListener,它是一个自动处置的小部件,因此会删除它创建的订阅。
BlocListener<BlocA, BlocAState>(
  listener: (context, state) {
    // do stuff here based on BlocA's state
  },
  child: Container(),
)

【讨论】:

  • 我喜欢第二种选择。不知道该功能。将尝试并让您知道结果。非常感谢。
猜你喜欢
  • 2021-10-24
  • 1970-01-01
  • 1970-01-01
  • 2019-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多