Flutter使用flutter_svg渲染SVG字符串报错:Future不是Widget
Hey there, let's break down what's going wrong and fix this issue quickly:
The Root Cause
Your displaySVG() method is marked as async, which means it returns a Future<void> instead of a Widget. When you try to put this directly into the Container's child, Flutter throws that type mismatch error because it expects a Widget, not a Future.
On top of that, your manual Canvas drawing approach has a couple of issues (like an uninitialized PictureRecorder and no step to convert the picture into a renderable Image widget), so we can simplify this a lot using flutter_svg's built-in tools.
Solution 1: Use SvgPicture.string() (Simplest Approach)
flutter_svg provides a ready-to-use widget that renders SVG directly from a string—no need to handle DrawableRoot or Picture manually. Here's the corrected code:
import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; class KanjiGradeGenerator extends StatefulWidget { @override _KanjiGradeState createState() => _KanjiGradeState(); } class _KanjiGradeState extends State<KanjiGradeGenerator> { final String rawSvg = '''<?xml version="1.0" encoding="UTF-8"?> <svg xmlns="http://www.w3.org/2000/svg" width="109" height="109" viewBox="0 0 109 109"> <g id="kvg:StrokePaths_080a1" style="fill:none;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;"> <path id="kvg:080a1-s1" d="M20.22,18.74c0.77,0.77,0.79,2.14,0.8,3.05C21.38,62,20.62,75,11.5,89.39"/> </g> </svg>'''; @override Widget build(BuildContext context) { return Scaffold( body: Container( // Use SvgPicture.string directly to render your SVG string child: SvgPicture.string( rawSvg, width: 200, // Adjust size as needed height: 200, fit: BoxFit.contain, ), ), ); } }
Solution 2: If You Need Async Processing (Using FutureBuilder)
If you ever need to load the SVG string asynchronously (e.g., from a network call or local file), you can use FutureBuilder to handle the async operation and render the Widget once it's ready:
import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; class KanjiGradeGenerator extends StatefulWidget { @override _KanjiGradeState createState() => _KanjiGradeState(); } class _KanjiGradeState extends State<KanjiGradeGenerator> { // Simulate an async SVG load (replace with your actual logic) Future<String> _loadSvgString() async { await Future.delayed(const Duration(milliseconds: 500)); return '''<?xml version="1.0" encoding="UTF-8"?> <svg xmlns="http://www.w3.org/2000/svg" width="109" height="109" viewBox="0 0 109 109"> <g id="kvg:StrokePaths_080a1" style="fill:none;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;"> <path id="kvg:080a1-s1" d="M20.22,18.74c0.77,0.77,0.79,2.14,0.8,3.05C21.38,62,20.62,75,11.5,89.39"/> </g> </svg>'''; } @override Widget build(BuildContext context) { return Scaffold( body: FutureBuilder<String>( future: _loadSvgString(), builder: (context, snapshot) { if (snapshot.hasData) { // Render SVG once data is available return Container( child: SvgPicture.string( snapshot.data!, width: 200, height: 200, fit: BoxFit.contain, ), ); } else if (snapshot.hasError) { // Show error message if something goes wrong return Center(child: Text('Error loading SVG: ${snapshot.error}')); } else { // Show loading indicator while waiting return const Center(child: CircularProgressIndicator()); } }, ), ); } }
Key Takeaways
- Never return an async function directly as a Widget—use
FutureBuilderfor async operations that produce Widgets. - flutter_svg has built-in widgets like
SvgPicture.string(),SvgPicture.asset(), andSvgPicture.network()that handle all low-level rendering for you, so you don't need to mess withPictureorCanvasmanually unless you have a specific custom use case.
内容的提问来源于stack exchange,提问作者Jellyfish

