Flutter Bloc 使用 Timer 重新获取数据

Posted

技术标签:

【中文标题】Flutter Bloc 使用 Timer 重新获取数据【英文标题】:Flutter Bloc using Timer to refetch data 【发布时间】:2020-09-05 12:27:04 【问题描述】:

我正在尝试在 Flutter Bloc 中创建一个计时器,以便在调用 DataFetchRequested 事件后每 30 秒获取一次数据。


class DataBloc extends Bloc<BlocEvent, BlocState> 
  final Api _api;
  Timer _timer;

  DataBloc(this._api);

  @override
  BlocState get initialState => StateInitial();

  @override
  Stream<BlocState> mapEventToState(BlocEvent event) async* 
    if (event is DataFetchRequested) 
      _resetTimer((timer) => _fetchData());
      yield* _fetchData();
    
  

  Stream<BlocState> _fetchData() async* 
    yield StateLoading();

    try 
      final result = await _api.fetch();
      yield StateSuccess(result);
     catch (e) 
      _timer.cancel();
      yield StateFailure(e.toString());
    
  

  _resetTimer(void Function(Timer) onCallback) 
    _timer?.cancel();
    _timer = Timer.periodic(Duration(seconds: 1), onCallback);
  

  @override
  Future<void> close() 
    _timer?.cancel();
    return super.close();
  



但是,当以这种方式调用时,计时器不会做任何事情。

尝试改变

_resetTimer((timer) => fetchFn);

yield* _resetTimer((timer) async* 
  yield* fetchFn;
);

导致错误:

Tried calling: listen(Closure: (Object) => void from Function '_add@4048458':., cancelOnError: false, onDone: Closure: () => void from Function '_close@4048458':., onError: Closure: (Object, StackTrace) => void from Function '_addError@4048458':.) occurred in bloc Instance of 'DataBloc'.
#0      Object.noSuchMethod  (dart:core-patch/object_patch.dart:53:5)
#1      new _AddStreamState  (dart:async/stream_controller.dart:900:34)
#2      new _StreamControllerAddStreamState  (dart:async/stream_controller.dart:952:9)
#3      _StreamController.addStream  (dart:async/stream_controller.dart:571:13)
#4      _AsyncStarStreamController.addStream  (dart:async-patch/async_patch.dart:206:37)
#5      DataBloc.mapEventToState 
package:app/…/data/DataBloc.dart:33
<asynchronous suspension>
#6      Bloc._bindEventsToStates.<anonymous closure> <…>

是否可以在 Bloc 中使用 Timer 每 30 秒获取一次数据?

尝试使用 Stream.periodic,但也失败了。

我能够通过在演示小部件中使用计时器并每 30 秒调用一次事件来实现我想要的,但我想将此逻辑从演示小部件移动到 DataBloc - 这可能吗?

【问题讨论】:

在这里查看我对类似问题的回答:***.com/questions/56446763/… @Er1 遗憾的是,这个答案没有帮助,因为您正在调用返回类型为 Future 的方法。我需要调用一个返回类型为Stream&lt;BlocState&gt; 的方法。调用具有Stream 返回类型的方法时 - 计时器回调失败。 【参考方案1】:

我认为这应该可行;

class DataBloc extends Bloc<BlocEvent, BlocState> 
  final Api _api;
  StreamSubscription _periodicSubscription;

  DataBloc(this._api);

  @override
  BlocState get initialState => StateInitial();

  @override
  Stream<BlocState> mapEventToState(BlocEvent event) async* 
    if (event is DataFetchRequested) 
      yield StateLoading();
      if(_periodicSubscription == null) 
        _periodicSubscription ??=
            Stream.periodic(const Duration(seconds: 30), (x) => x).listen(
                    (_) => add(const FetchEvent()),
                onError: (error) =>
                    print("Do something with $error")
            );
       else 
        _periodicSubscription.resume();
      
    
    if(event is FetchEvent)
      yield StateLoading();

      try 
        final result = await _api.fetch();
        yield StateSuccess(result);
       catch (e) 
        _periodicSubscription.pause();
        yield StateFailure(e.toString());
      
    
  

  @override
  Future<void> close() async 
    await _periodicSubscription?.cancel();
    _periodicSubscription = null;
    return super.close();
  

FetchEvent 是您必须创建的新事件类。

【讨论】:

以上是关于Flutter Bloc 使用 Timer 重新获取数据的主要内容,如果未能解决你的问题,请参考以下文章

Flutter Bloc 状态管理

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

谁能说出 Flutter 中“flutter_bloc”和“bloc”包的区别

Flutter:BLoC 包 - bloc 提供者

使用 flutter_bloc 库有啥缺点

如何保持我的bottomNavigationBar Cubit BLoc Flutter的状态?