Flutter从JSON加载Marker到GoogleMap失败,报build返回空异常
解决Flutter GoogleMap标记不显示及Build返回Null的问题
我来帮你排查下问题所在,你遇到的两个问题其实是相关的,咱们一步步解决:
问题1:Build函数返回Null的异常
你的FutureBuilder的builder方法只做了JSON解析和标记列表赋值,没有返回任何Widget,这就违反了Flutter的Build规则——builder必须返回一个Widget,所以控制台抛出了A build function returned null的异常。
问题2:标记不显示
就算没有这个异常,你的标记也不会显示,因为解析完JSON生成标记列表后,没有调用setState()通知Flutter框架更新UI,地图组件不会感知到allMarkers的变化,自然不会渲染新标记。
另外,你还没处理Future的不同状态(加载中、错误、数据就绪),这会导致在数据还没加载完成时就尝试解析snapshot.data,可能引发空指针问题。
修改后的完整代码
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:flutter/services.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: MyHomePage(), ); } } class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { Future<String>? _future; Future<String> loadString() async => await rootBundle.loadString('assets/data.json'); List<Marker> allMarkers = []; GoogleMapController? _controller; @override void initState() { super.initState(); _future = loadString(); } @override Widget build(BuildContext context) { return Scaffold( body: SizedBox( height: MediaQuery.of(context).size.height, width: MediaQuery.of(context).size.width, child: Stack( children: <Widget>[ GoogleMap( initialCameraPosition: const CameraPosition(target: LatLng(40.7128, -74.0060), zoom: 1.0), markers: Set.from(allMarkers), onMapCreated: mapCreated, ), // 将FutureBuilder放在地图上层,不影响地图显示,同时处理数据 FutureBuilder( future: _future, builder: (context, AsyncSnapshot<String> snapshot) { // 处理加载状态 if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } // 处理错误状态 if (snapshot.hasError) { return Center(child: Text('加载数据失败: ${snapshot.error}')); } // 数据就绪时解析并更新标记 if (snapshot.hasData) { List<dynamic> parsedJson = jsonDecode(snapshot.data!); setState(() { allMarkers = parsedJson.map((element) { return Marker( markerId: MarkerId(element['id']), position: LatLng(element['x'], element['y']), ); }).toList(); }); // 返回空Widget,因为我们不需要额外UI return const SizedBox.shrink(); } // 默认返回空Widget return const SizedBox.shrink(); }, ), ], ), ), ); } void mapCreated(GoogleMapController controller) { setState(() { _controller = controller; }); } }
关键修改点
- 修复FutureBuilder的返回值:在builder的所有分支都返回了合法的Widget(加载指示器、错误文本、空Widget),解决了返回Null的异常。
- 添加setState更新标记:解析完JSON后调用
setState(),让Flutter重新渲染地图,加载新的标记。 - 完善Future状态处理:增加了加载中、错误状态的UI提示,避免数据未就绪时的异常。
- 调整组件层级:把GoogleMap放在底层,FutureBuilder放在上层,不影响地图显示逻辑。
另外,别忘了确认你的pubspec.yaml已经正确配置了assets路径:
assets: - assets/data.json
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

