Flutter 控制台中未显示颤振异常
我正在调试一个颤振应用程序。我注意到,在某些情况下,异常会被抛出,但不会显示在控制台中。所以我花了一段时间才知道有例外。这是浪费了很多时间 下面是一个小代码片段来说明这个问题。使用RaisedButton显示异常,但不使用Flutter 控制台中未显示颤振异常,flutter,dart,exception,textfield,Flutter,Dart,Exception,Textfield,我正在调试一个颤振应用程序。我注意到,在某些情况下,异常会被抛出,但不会显示在控制台中。所以我花了一段时间才知道有例外。这是浪费了很多时间 下面是一个小代码片段来说明这个问题。使用RaisedButton显示异常,但不使用TextField。我必须添加一个try/catch来打印异常,否则它是不可见的 问题不是错误本身,问题是错误没有显示出来。请告诉我如何显示所有异常 void main() => runApp(Test()); class Test extends StatelessW
TextField
。我必须添加一个try/catch来打印异常,否则它是不可见的
问题不是错误本身,问题是错误没有显示出来。请告诉我如何显示所有异常
void main() => runApp(Test());
class Test extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
// EXCEPTION CAUGHT:
// child: RaisedButton(child: Text('Test'), onPressed: () => throw Exception()),
// EXCEPTION NOT CAUGHT:
child: TextField(onSubmitted: (value) => throw Exception()),
),
),
);
}
}
如果你想的话,你可以去“颤振回购”
下面是关于它如何工作的基本解释
如果查看源代码,RaisedButton.onPressed
被委托给InkWell.onTap
,然后转到InkResponse.onTap
,然后在以下内容的最后一行调用它:
void\u handleTap(构建上下文){
_currentSplash?.confirm();
_currentSplash=null;
updateHighlight(_HighlightType.pressed,值:false);
如果(widget.onTap!=null){
if(widget.enableffeedback)
反馈。forTap(上下文);
onTap();
}
}
这由手势识别器
包装在invokeCallback
中,执行try catch
并将错误转换为错误
,您可以在控制台上看到格式良好的错误
T invokeCallback(字符串名称,识别器回调,{String debugReport()}){
断言(回调!=null);
T结果;
试一试{
断言(){
if(DebugPrintRecognitizerCallBackstrace){
最终字符串report=debugReport!=null?debugReport():null;
//下一行中的19是所使用前缀的宽度
//_在arena.dart中调试LogDiagnostic。
最终字符串前缀=debugPrintGestureArenaDiagnostics?''*19+'❙ ' : '';
debugPrint(“$prefix$this calling$name callback.${report?.isNotEmpty==true?”$report:“}”);
}
返回true;
}());
结果=回调();
}捕获(异常、堆栈){
信息采集器;
断言(){
收集器=()同步*{
产生StringProperty('Handler',名称);
产生DiagnosticsProperty(“识别器”,此,样式:DiagnosticsTreeStyle.errorProperty);
};
返回true;
}());
FlatterError.reportError(FlatterErrorDetails(
例外:例外,,
堆栈:堆栈,
图书馆:"手势",,
上下文:ErrorDescription('处理手势时'),
信息收集器:收集器
));
}
返回结果;
}
另一方面,TextField.onSubmitted
被传递给一个EditableText.onSubmitted
,并在以下内容的最后一行调用它:
void\u结束编辑(bool应该取消焦点){
//现在用户已完成编辑,请执行任何必要的操作。
if(widget.onEditingComplete!=null){
widget.onEditingComplete();
}否则{
//如果开发人员未提供
//onEditingComplete回调:完成编辑并移除焦点。
widget.controller.clearComposing();
如果(应该取消焦点)
widget.focusNode.unfocus();
}
//使用用户提交的内容调用可选回调。
if(widget.onSubmitted!=null)
widget.onSubmitted(_value.text);
}
这由MethodChannel包装:
Future\u handleAsMethodCall(ByteData消息,Future处理程序(MethodCall调用))异步{
最终方法调用=codec.decodeMethodCall(消息);
试一试{
返回codec.encodeSuccessDevelope(等待处理程序(调用));
}平台上异常捕获(e){
返回codec.encodeErrorEnvelope(
代码:e.code,
信息:e.message,
细节:即细节,
);
}关于丢失插件异常{
返回null;
}捕获(e){
返回codec.encodeErrorEnvelope(代码:“error”,消息:e.toString(),详细信息:null);
}
}
最后一个catch(e)
被激活,然后您就看不到错误了
我怀疑如果您编译应用程序以发布,您会看到它,因为Dart VM在异步代码的调试模式下传递异常方面存在问题(我在这里过于简化了)。这最终是一个有趣的发现
TextField
的onSubmitted
方法(以及TextFormField
的onfielsubmitted
方法)是从EditableText
基类的performation
方法调用的,该基类最终作为平台频道消息的结果调用(特别是说“我现在编辑完这个文本字段了”的消息)。在MethodChannel
类中,负责将事件传递给小部件的方法是:
Future\u handleAsMethodCall(ByteData消息,Future处理程序(MethodCall调用))异步{
最终方法调用=codec.decodeMethodCall(消息);
试一试{
返回codec.encodeSuccessDevelope(等待处理程序(调用));
}平台上异常捕获(e){
返回codec.encodeErrorEnvelope(
代码:e.code,
信息:e.message,
细节:即细节,
);
}关于丢失插件异常{
返回null;
}捕获(e){
返回codec.encodeErrorEnvelope(代码:“error”,消息:e.toString(),详细信息:null);
}
}
如您所见,方法调用被包装在一个try/catch中,它吸收错误并将其作为错误响应返回给平台,而不是让错误自然冒泡。其结果是错误消息由内部BinaryMessenger
处理,而不是由Dart本身处理。从那里它结束在该方法中,这是一种固有的方法,也是一个研究的死胡同(除非您了解颤振的平台规范)