Flutter Build方法处理多个Future时markers未初始化如何解决?
解决方案
方案1:使用Future.wait合并异步任务(推荐)
这个方案可以避免嵌套FutureBuilder,代码结构更清晰,逻辑更易维护。
第一步:调整状态变量定义
// 保留原来的两个异步任务 late Future<Position> _init; late Future<List<Marker>> markers; // 新增合并后的总异步任务 late Future<List<dynamic>> _allInitData;
第二步:修改initState逻辑,合并异步任务
@override void initState() { super.initState(); // 原有初始化逻辑不变 _init = 你原来的初始化Position的方法(); markers = getMarkers(); // 合并两个异步任务,两个任务都完成才会触发FutureBuilder的完成状态 _allInitData = Future.wait([_init, markers]); }
第三步:修改Build方法的FutureBuilder逻辑
@override Widget build(BuildContext context) { return FutureBuilder<List<dynamic>>( future: _allInitData, builder: (context, snapshot) { // 处理加载中状态 if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } // 处理错误状态 if (snapshot.hasError) { return Center(child: Text("加载失败:${snapshot.error}")); } // 按Future.wait传入的顺序取值即可 final Position position = snapshot.data![0] as Position; final List<Marker> markerList = snapshot.data![1] as List<Marker>; return FlutterMap( // 你的原有FlutterMap配置 layers: [ // 你的原有其他图层配置 MarkerLayerOptions( markers: markerList, // 直接传入已加载完成的marker列表 ), ], ); } ); }
方案2:嵌套FutureBuilder(需分步处理异步任务时可选)
如果两个异步任务有先后依赖,或者需要分别展示不同阶段的加载状态,可以用嵌套写法:
@override Widget build(BuildContext context) { return FutureBuilder<Position>( future: _init, builder: (context, positionSnapshot) { if (positionSnapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } if (positionSnapshot.hasError) { return Center(child: Text("位置加载失败:${positionSnapshot.error}")); } final Position position = positionSnapshot.data!; // 位置加载完成后再加载marker列表 return FutureBuilder<List<Marker>>( future: markers, builder: (context, markerSnapshot) { if (markerSnapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } if (markerSnapshot.hasError) { return Center(child: Text("标记加载失败:${markerSnapshot.error}")); } final List<Marker> markerList = markerSnapshot.data!; return FlutterMap( // 原有配置 layers: [ // 原有其他图层 MarkerLayerOptions(markers: markerList), ], ); } ); } ); }
关键注意点
- 不要在FutureBuilder的
future参数中直接创建Future实例,必须提前在initState中初始化,否则每次组件刷新都会重新执行异步请求,导致资源浪费和逻辑异常 - 必须处理加载、错误两种边缘状态,不要直接使用
!强制拆包snapshot.data,避免空指针异常 - Future.wait返回的列表顺序和传入的Future顺序完全一致,取值时注意不要搞混对应关系
内容的提问来源于stack exchange,提问作者Lorenzo Cutrupi
相关产品推荐
相关产品推荐

