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<BlocState>
的方法。调用具有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 重新获取数据的主要内容,如果未能解决你的问题,请参考以下文章