【发布时间】:2021-05-30 14:26:06
【问题描述】:
麻烦
我构建了 Flutter 应用程序 + Dart。
现在我试图在 ONE 地方(类)AND showAlertDialog 中捕获所有未来的异常。
Flutter Docs 提出了 3 个解决方案来捕获 async 错误:
- runZonedGuarded
- ... async{ 等待 future() }catch(e){ ... }
- Future.onError
但是没有人可以实现所有目标(以最纯粹的形式):
第一:不能在widget的build中运行(需要返回Widget,但是返回Widget?。
第二:在build 中工作,但不要捕获异步错误,这些错误是由未等待的期货引发的,并且是“脏的”(强制使用WidgetBinding.instance.addPostFrameCallback。我可以确保等待期货(这增加了麻烦) ),但我无法检查是否确保它是第三方库。因此,这是不好的情况。
第三:类似于第二。而且看起来很可怕。
我的(可以忍受的)解决方案
我得到了第一个解决方案并添加了一些细节。所以,
我创建了ZonedCatcher,它显示有异常的AlertDialog,或者如果它不知道在哪里显示AlertDialog,则会累积异常(BuildContext 尚未提供)。
AlertDialog 需要MaterialLocalizations,所以BuildContext 取自MaterialApp 的孩子MaterialChild。
void main() {
ZonedCatcher().runZonedApp();
}
...
class ZonedCatcher {
BuildContext? _materialContext;
set materialContext(BuildContext context) {
_materialContext = context;
if (_exceptionsStack.isNotEmpty) _showStacked();
}
final List<Object> _exceptionsStack = [];
void runZonedApp() {
runZonedGuarded<void>(
() => runApp(
Application(
MaterialChild(this),
),
),
_onError,
);
}
void _onError(Object exception, _) {
if (_materialContext == null) {
_exceptionsStack.add(exception);
} else {
_showException(exception);
}
}
void _showException(Object exception) {
print(exception);
showDialog(
context: _materialContext!,
builder: (newContext) => ExceptionAlertDialog(newContext),
);
}
void _showStacked() {
for (var exception in _exceptionsStack) {
_showException(exception);
}
}
}
...
class MaterialChild extends StatelessWidget {
MaterialChild(this.zonedCatcher);
final ZonedCatcher zonedCatcher;
@override
Widget build(BuildContext context) {
zonedCatcher.materialContext = context; //!
...
}
}
缺陷
- 目前我不知道如何用多个页面组织应用程序。
materialContext只能从MaterialApp孩子中获取,但页面已经在MaterialApp小部件中设置。也许,我会在所有页面中注入ZonedCatcher,并且构建页面将重新设置materialContext。但我可能会面临GlobalKey的问题,比如在手势上同时通过某些页面重置materialContext。 - 这不是常见的模式,我必须彻底记录这一刻,这个解决方案使其他程序员更难理解项目。
- Flutter 的创建者没有预见到这个解决方案,它可能会在新的包上发生重大变化。
有什么想法吗?
【问题讨论】:
-
我不知道你为什么试图过多地简化捕获异常,但我认为如果你使用 GetX 包,你可以在没有上下文的情况下显示对话框。我认为这不是一个顺利的解决方案,但它似乎有效
标签: flutter dart architecture