通过Navigator Flutter传递BlocProvider

时间:2020-04-09 11:06:25

标签: flutter bloc

我正在使用flutter_bloc软件包,并从抽屉中的按钮发送一个SchedulerEvent来加载已保存的警报,并提供SchedulerBloc,我导航到一个{{1} }的BlocListener可以监听SchedulerScreen并显示所有已设置的警报。 按下按钮面团时,我在按钮的SchedulerState回调中收到由BlocProvider.of<SchedulerBloc>(context).add(LoadAlarms());引起的错误。

onPressed:

这是导航到E/flutter (13058): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: NoSuchMethodError: The method 'handleError' was called on null. E/flutter (13058): Receiver: null E/flutter (13058): Tried calling: handleError(Closure: (Object, [StackTrace]) => void from Function '_handleError@73502097':.) E/flutter (13058): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5) E/flutter (13058): #1 Bloc._bindStateSubject.<anonymous closure> (package:bloc/src/bloc.dart:155:44) E/flutter (13058): #2 Stream.asyncExpand.onListen.<anonymous closure> (dart:async/stream.dart:576:30) E/flutter (13058): #3 _rootRunUnary (dart:async/zone.dart:1134:38) E/flutter (13058): #4 _CustomZone.runUnary (dart:async/zone.dart:1031:19) E/flutter (13058): #5 _CustomZone.runUnaryGuarded (dart:async/zone.dart:933:7) E/flutter (13058): #6 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:338:11) E/flutter (13058): #7 _DelayedData.perform (dart:async/stream_impl.dart:593:14) E/flutter (13058): #8 _StreamImplEvents.handleNext (dart:async/stream_impl.dart:709:11) E/flutter (13058): #9 _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:669:7) E/flutter (13058): #10 _rootRun (dart:async/zone.dart:1122:38) E/flutter (13058): #11 _CustomZone.run (dart:async/zone.dart:1023:19) E/flutter (13058): #12 _CustomZone.runGuarded (dart:async/zone.dart:925:7) E/flutter (13058): #13 _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:965:23) E/flutter (13058): #14 _rootRun (dart:async/zone.dart:1126:13) E/flutter (13058): #15 _CustomZone.run (dart:async/zone.dart:1023:19) E/flutter (13058): #16 _CustomZone.runGuarded (dart:async/zone.dart:925:7) E/flutter (13058): #17 _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:965:23) E/flutter (13058): #18 _microtaskLoop (dart:async/schedule_microtask.dart:43:21) E/flutter (13058): #19 _startMicrotaskLoop (dart:async/schedule_microtask.dart:52:5) E/flutter (13058): 的按钮:

SchedulerScreen

这是FlatButton.icon( icon: Image.asset( 'assets/schedulerButton.png', height: 55, width: 55, ), label: Text( 'Check scheduler', style: TextStyle( color: Colors.white, fontSize: 18, fontWeight: FontWeight.w400), ), color: Colors.transparent, onPressed: () { // TODO call LoadRoutes and navigate to SchedulerScreen print('pressed'); cache.play('tableViewOpen.mp3'); BlocProvider.of<SchedulerBloc>(context) .add(LoadAlarms()); // old // old // Navigator.push( // context, // MaterialPageRoute( // builder: (context) => // SchedulerScreen(widget.key, widget.user), // ), // ); // new Navigator.push( context, MaterialPageRoute<SchedulerScreen>(builder: (_) { return BlocProvider.value( value: BlocProvider.of<SchedulerBloc>(context), child: SchedulerScreen(widget.key, widget.user), ); }), ); }, ), ,应显示SchedulerScreen随附的已保存警报:

SchedulerState

如您所见,我最初是直接在class SchedulerScreen extends StatefulWidget { final User user; SchedulerScreen(Key key, this.user); @override _SchedulerScreenState createState() => _SchedulerScreenState(); } class _SchedulerScreenState extends State<SchedulerScreen> { AudioCache cache = new AudioCache(); List<Alarm> alarms = []; List<SchedulerCell> cells = []; @override Widget build(BuildContext context) { cache.loadAll(['click.mp3', 'tableViewOpen.mp3', 'tableViewClose.mp3']); dynamic backButton = Platform.isIOS ? CupertinoIcons.back : Icons.arrow_back; dynamic addButton = Platform.isIOS ? CupertinoIcons.add : Icons.add; // return BlocProvider<SchedulerBloc>( // create: (BuildContext context) => SchedulerBloc(), // child: BlocListener<SchedulerBloc, SchedulerState>( return BlocListener<SchedulerBloc, SchedulerState>( listener: (BuildContext context, SchedulerState state) { if (state is AlarmsLoaded) { setState(() { alarms = state.alarms; cells = state.cells; }); } }, child: Scaffold( // return Scaffold( appBar: AppBar( elevation: 0, backgroundColor: Colors.transparent, leading: IconButton( icon: Icon(backButton), color: Colors.redAccent, onPressed: () { cache.play('tableViewClose.mp3'); Navigator.pop(context); }), title: Text( 'Controlli tragitti', textAlign: TextAlign.center, style: TextStyle( color: Colors.orange, fontSize: 22, fontWeight: FontWeight.w500, letterSpacing: 1), ), centerTitle: true, actions: <Widget>[ IconButton( icon: Icon(addButton), color: Colors.redAccent, onPressed: () { // TODO navigate to AddEditCheckScreen cache.play('tableViewOpen.mp3'); // Navigator.push( // context, // MaterialPageRoute( // builder: (context) => AddEditCheckScreen( // key: widget.key, isEditing: false, user: widget.user), // ), // ); Navigator.push( context, MaterialPageRoute<AddEditCheckScreen>(builder: (_) { return BlocProvider.value( value: BlocProvider.of<SchedulerBloc>(context), child: AddEditCheckScreen( key: widget.key, isEditing: false, user: widget.user), ); }), ); }, ) ], ), body: Container(), // body: ListView.builder( // padding: EdgeInsets.all(20), // itemCount: alarms.length, // itemBuilder: (BuildContext context, int index) => Container( // color: Colors.transparent, // child: cells[index], // ), // ), // ), ), ); } } 中创建一个BlocProvider,因为从那里我还添加了新警报,但是当从中发送事件时,我遇到了SchedulerScreen错误,因此现在提供它直接从我从中导航的屏幕上,但是设置不正确。 您能在这里发现我做错了吗? 一如既往,非常感谢您的时间和帮助。

1 个答案:

答案 0 :(得分:0)

我发现mapEventToState的{​​{1}}方法中的错误未声明为SchedulerBloc。添加后,一切都会按预期进行。