对于“一次性错误”,redux有点笨拙。一般来说,有两种处理方法:
- 您可以将错误保存在存储中,并在存储中存在错误时显示错误覆盖。从商店中删除错误以关闭覆盖。
- 将错误显示视为“一次性”副作用(就像播放声音一样)。我认为这是更好的解决方案,特别是如果您要使用小吃店。
我不确定中间件的外观如何,但是在网络请求失败后,您会将错误对象推送到rxdart
Subject或中
StreamController。现在您有一个
Stream错误。
作为您的直接子级
StoreProvider,创建自己
InheritedWidget的错误流,名为
SyncErrorProvider:
class SyncErrorProvider extends InheritedWidget { const SyncErrorProvider({Key key, this.errors, @required Widget child}) : assert(child != null), super(key: key, child: child); final Stream<Object> errors; static SyncErrorProvider of(BuildContext context) { return context.inheritFromWidgetOfExactType(SyncErrorProvider) as SyncErrorProvider; } @override bool updateShouldNotify(SyncErrorProvider old) => errors != old.errors;}继承的小部件应包装您的
MaterialApp。现在,您有一种简单的方法,可以使用
SyncErrorProvider.of(context).errorsfrom
从任何路径访问错误流
didChangeDependencies。
在小吃店中显示错误有点困难,因为小吃店的位置取决于页面布局(FAB,底部导航…),有时出现的小吃店会移动其他UI元素。
处理快餐栏创建的最佳方法实际上取决于您的应用程序。我也不确定这些错误会多久发生一次,所以也许不要花太多时间。
两种方法各有利弊:
在页面支架中显示错误
在每个具有脚手架的屏幕中,侦听错误流并在本地脚手架中显示小吃店。确保在取消放置小部件时退订。
这种方法的优势在于,小吃栏是页面UI的一部分,并将移动支架的其他元素。
缺点是,如果存在对话框或没有支架的屏幕,则该错误将不可见。
class HomePage extends StatefulWidget { @override _HomePageState createState() => _HomePageState();}class _HomePageState extends State<HomePage> { StreamSubscription _errorsSubscription; final _scaffoldKey = GlobalKey<ScaffoldState>(); @override void didChangeDependencies() { super.didChangeDependencies(); if(_errorsSubscription == null) { _errorsSubscription = SyncErrorProvider.of(context).errors.listen((error) { _scaffoldKey.currentState.showSnackBar(SnackBar(content: Text(error.toString()))); }); } } @override void dispose() { _errorsSubscription.cancel(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( key: _scaffoldKey, body: ..., ); }}在全球范围内安装错误小吃店
该脚手架仅用于小吃店,仅此而已。优点是始终保证错误是可见的,缺点是它们将与FAB和底部条重叠。
class MyApp extends StatefulWidget { final Stream<Object> syncErrors; // coming from your store/middleware MyApp({Key key, this.syncErrors}) : super(key: key); @override _MyAppState createState() => _MyAppState();}class _MyAppState extends State<MyApp> { StreamSubscription _errorsSubscription; final _errorScaffoldKey = GlobalKey<ScaffoldState>(); @override void initState() { // TODO: implement initState super.initState(); _errorsSubscription = widget.syncErrors.listen((error) { _errorScaffoldKey.currentState.showSnackBar(SnackBar(content: Text(error.toString()))); }); } @override void dispose() { _errorsSubscription.cancel(); super.dispose(); } @override Widget build(BuildContext context) { return MaterialApp( builder: (context, child) { Scaffold( key: _errorScaffoldKey, body: child, ); }, ); }}


