我想解析 SVG 字符串来测试它是否是有效的 SVG。这可能吗?
我在错误处理方面遇到了一些困难。 Try/catch 不起作用,RunZonedGuarded 也不起作用。要明白我的意思,请尝试加载无效的 svg 字符串:
try {
SvgPicture.string('not svg');
}
catch {
//not catching
}
下面的方法可以捕获错误而不会使应用程序崩溃,但不是很优雅。令人不快的 android 错误显示在图像框中并溢出。
FutureBuilder<String>(
future: Future.value(_shopLogoSvg),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return SvgPicture.string(snapshot.data!,
fit: BoxFit.contain,
allowDrawingOutsideViewBox: false,);
} else {
return const Center(
child: CircularProgressIndicator()); // or any other loading indicator
}
},
);
拥有可用于在加载之前解析不受信任的 SVG 字符串的
SvgPicture.parse
方法将会有所帮助。
或者也许有更好的方法来正确处理错误
flutter_svg
?
任何帮助表示赞赏!
关键是使用
SvgStringLoader
并尝试在调用 loadBytes()
方法时捕获错误,如下所示:
class FooSVG extends StatefulWidget {
const FooSVG({
super.key,
required this.svg,
this.onError,
});
final String svg;
final Widget Function(dynamic error)? onError;
@override
State<FooSVG> createState() => _FooSVGState();
}
class _FooSVGState extends State<FooSVG> {
Future<SvgStringLoader>? _loaded;
@override
void didChangeDependencies() {
debugPrint('FooSVG.didChangeDependencies');
super.didChangeDependencies();
_loaded = _load();
}
@override
void didUpdateWidget(FooSVG oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.svg != widget.svg) {
debugPrint('FooSVG.didUpdateWidget reload');
_loaded = _load();
} else {
debugPrint('FooSVG.didUpdateWidget no change');
}
}
@override
Widget build(BuildContext context) {
return FutureBuilder<SvgStringLoader>(
future: _loaded,
builder: (ctx, snapshot) {
// debugPrint(snapshot.toString());
return switch (snapshot) {
(AsyncSnapshot<SvgStringLoader> s) when s.hasData => SvgPicture(s.data!),
(AsyncSnapshot s) when !s.hasError => const UnconstrainedBox(),
(AsyncSnapshot s) => _error(s),
};
}
);
}
Future<SvgStringLoader> _load() async {
try {
final loader = SvgStringLoader(widget.svg);
await loader.loadBytes(context);
return loader;
} catch (e) {
debugPrint('FooSVG error: $e');
rethrow;
}
}
Widget _error(AsyncSnapshot snapshot) {
return widget.onError?.call(snapshot.error!) ?? Text(snapshot.error!.toString());
}
}
现在用以下方式调用它:
FooSVG(
svg: '''
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40">
<g>
<g>
<path d="M4,4h7.59086V6.86658H7.43044V33.13342h4.16042V36H4Z" fill="#727474"/>
<path d="M28.40914,33.13342h4.159V6.86658h-4.159V4H36V36H28.40914Z" fill="#727474"/>
</g>
<path d="M17.61105,13.53573H11V9.01825H29v4.51748H22.39077V32.88H17.61105Z"/>
</g>
</svg>''',
onError: (error) {
return switch (error) {
XmlParserException(:final message, :final line, :final column) =>
Text('parser error, $message at [$line:$column]'),
_ => Text('other error, $error'),
};
},
),
如果您想检查错误检查,请将
<svg
替换为 <svg,
例如