मैं एक स्पंदन ऐप डीबग करने का प्रयास कर रहा हूं। मैंने देखा कि कुछ मामलों में अपवाद फेंके जाते हैं, लेकिन कंसोल में प्रदर्शित नहीं होते हैं। इसलिए मुझे यह जानने में थोड़ा समय लगा कि कोई अपवाद है। यह बहुत समय बर्बाद होता है।
समस्या दिखाने के लिए यहां एक छोटा कोड स्निपेट है। उठाया बटन के साथ अपवाद दिखाया गया है, लेकिन TextField
के साथ नहीं। मुझे अपवाद मुद्रित करने के लिए एक कोशिश/पकड़ जोड़ने के लिए मजबूर होना पड़ता है, अन्यथा यह अदृश्य है।
समस्या स्वयं त्रुटि नहीं है, समस्या यह है कि त्रुटि दिखाई नहीं देती है। कृपया मुझे बताएं कि मैं सभी अपवाद कैसे दिखा सकता हूं।
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()),
),
),
);
}
}
2 जवाब
यह एक दिलचस्प शिकार बनकर समाप्त हुआ।
onSubmitted
की विधि TextField
(साथ ही TextFormField
की onFieldSubmitted
विधि) को EditableText
की performAction
विधि से कहा जाता है। बेस क्लास, जिसे अंततः एक प्लेटफ़ॉर्म चैनल संदेश के परिणाम के रूप में कहा जाता है (विशेष रूप से वह संदेश जो कहता है "मैंने अब इस टेक्स्ट फ़ील्ड को संपादित किया है")। MethodChannel
वर्ग के भीतर, इवेंट को विजेट में पास करने के लिए जिम्मेदार तरीका है _handleAsMethodCall
विधि:
Future<ByteData> _handleAsMethodCall(ByteData message, Future<dynamic> handler(MethodCall call)) async {
final MethodCall call = codec.decodeMethodCall(message);
try {
return codec.encodeSuccessEnvelope(await handler(call));
} on PlatformException catch (e) {
return codec.encodeErrorEnvelope(
code: e.code,
message: e.message,
details: e.details,
);
} on MissingPluginException {
return null;
} catch (e) {
return codec.encodeErrorEnvelope(code: 'error', message: e.toString(), details: null);
}
}
जैसा कि आप देख सकते हैं, विधि कॉल को एक कोशिश/पकड़ में लपेटा जाता है जो त्रुटियों को अवशोषित करता है और त्रुटि को स्वाभाविक रूप से बबल करने की अनुमति देने के बजाय त्रुटि प्रतिक्रियाओं के रूप में प्लेटफ़ॉर्म पर लौटाता है। इसका परिणाम यह होता है कि त्रुटि संदेश को आंतरिक BinaryMessenger
द्वारा नियंत्रित किया जाता है, न कि स्वयं डार्ट द्वारा। वहां से यह Window._respondToPlatformMessage
पर समाप्त होता है। विधि, जो एक देशी-बाध्य विधि और एक खोजी डेड-एंड है (जब तक कि आपको फ़्लटर के प्लेटफ़ॉर्म-विशिष्ट मूल कार्यान्वयन का ज्ञान न हो)।
मुझे यकीन नहीं है कि यह इरादा व्यवहार या बग है, लेकिन किसी भी मामले में, परिणाम यह प्रतीत होता है कि प्लेटफ़ॉर्म/विधि चैनल सिस्टम द्वारा त्रुटि अवशोषित हो जाती है। मैं फ़्लटर गिटहब पेज पर इसके लिए एक समस्या तैयार कर रहा हूं, और जब समस्या पोस्ट की जाती है तो इस उत्तर को लिंक के साथ अपडेट कर देगा।
संपादित करें: समस्या पृष्ठ यहां है।
आप चाहें तो फ़्लटर रेपो में इसे एक समस्या के रूप में दर्ज कर सकते हैं।
यह कैसे काम करता है, इसकी एक बुनियादी व्याख्या यहां दी गई है।
यदि आप स्रोत कोड को देखते हैं, तो RaisedButton.onPressed
को InkWell.onTap
को सौंप दिया जाता है, जो तब एक InkResponse.onTap
पर जाता है, जो इसे अंतिम पंक्ति में बुलाता है:
void _handleTap(BuildContext context) {
_currentSplash?.confirm();
_currentSplash = null;
updateHighlight(_HighlightType.pressed, value: false);
if (widget.onTap != null) {
if (widget.enableFeedback)
Feedback.forTap(context);
widget.onTap();
}
}
यह GestureRecognizer
द्वारा एक invokeCallback
में लिपटा हुआ है जो एक try-catch
करता है और त्रुटि को एक FlutterError
में बदल देता है जिसे आप अपने कंसोल पर अच्छी तरह से स्वरूपित देखते हैं।
T invokeCallback<T>(String name, RecognizerCallback<T> callback, { String debugReport() }) {
assert(callback != null);
T result;
try {
assert(() {
if (debugPrintRecognizerCallbacksTrace) {
final String report = debugReport != null ? debugReport() : null;
// The 19 in the line below is the width of the prefix used by
// _debugLogDiagnostic in arena.dart.
final String prefix = debugPrintGestureArenaDiagnostics ? ' ' * 19 + '❙ ' : '';
debugPrint('$prefix$this calling $name callback.${ report?.isNotEmpty == true ? " $report" : "" }');
}
return true;
}());
result = callback();
} catch (exception, stack) {
InformationCollector collector;
assert(() {
collector = () sync* {
yield StringProperty('Handler', name);
yield DiagnosticsProperty<GestureRecognizer>('Recognizer', this, style: DiagnosticsTreeStyle.errorProperty);
};
return true;
}());
FlutterError.reportError(FlutterErrorDetails(
exception: exception,
stack: stack,
library: 'gesture',
context: ErrorDescription('while handling a gesture'),
informationCollector: collector
));
}
return result;
}
दूसरी ओर TextField.onSubmitted
को EditableText.onSubmitted
में पास किया जाता है और इसे अंतिम पंक्ति में कहा जाता है:
void _finalizeEditing(bool shouldUnfocus) {
// Take any actions necessary now that the user has completed editing.
if (widget.onEditingComplete != null) {
widget.onEditingComplete();
} else {
// Default behavior if the developer did not provide an
// onEditingComplete callback: Finalize editing and remove focus.
widget.controller.clearComposing();
if (shouldUnfocus)
widget.focusNode.unfocus();
}
// Invoke optional callback with the user's submitted content.
if (widget.onSubmitted != null)
widget.onSubmitted(_value.text);
}
यह एक MethodChannel द्वारा लपेटा गया है:
Future<ByteData> _handleAsMethodCall(ByteData message, Future<dynamic> handler(MethodCall call)) async {
final MethodCall call = codec.decodeMethodCall(message);
try {
return codec.encodeSuccessEnvelope(await handler(call));
} on PlatformException catch (e) {
return codec.encodeErrorEnvelope(
code: e.code,
message: e.message,
details: e.details,
);
} on MissingPluginException {
return null;
} catch (e) {
return codec.encodeErrorEnvelope(code: 'error', message: e.toString(), details: null);
}
}
और वह अंतिम catch (e)
सक्रिय हो जाता है और फिर आपको कोई त्रुटि दिखाई नहीं देती है।
मुझे संदेह है कि यदि आप रिलीज करने के लिए अपने ऐप को संकलित करते हैं तो आप इसे देखेंगे, क्योंकि डार्ट वीएम को एसिंक्रोनस कोड के लिए डीबग मोड में अपवाद देने में समस्या है (मैं यहां चीजों को सरल बना रहा हूं)।
संबंधित सवाल
नए सवाल
flutter
स्पंदन Google द्वारा बनाई गई एक ओपन-सोर्स UI सॉफ़्टवेयर डेवलपमेंट किट है। इसका उपयोग Android, iOS, Linux, Mac, Windows, Google Fuchsia और वेब के लिए एक ही कोडबेस से एप्लिकेशन विकसित करने के लिए किया जाता है। स्पंदन ऐप्स डार्ट भाषा में लिखे गए हैं।