Flutter:使用Future JSON数据填充SliverList时遇问题求助
解决用Future填充SliverFixedExtentList的问题
嘿,我来帮你搞定这个问题!你碰到的两个错误,其实都是Sliver组件使用时的常见误区,咱们一步步拆解修复:
问题根源分析
- 非Sliver组件直接塞进slivers列表:CustomScrollView的
slivers数组只能放继承自RenderSliver的组件,你在else分支返回的Padding是普通Widget,直接放进去就触发了断言错误。 - Future传递方式错了:你把函数引用
_getMyListOfCustomJsonObjects传给了future参数,而不是调用函数得到的Future对象——这会导致每次Widget重建都重新发起API请求,甚至引发重复GlobalKey的问题。 - 状态判断不够严谨:只靠
snapshot.data != null判断状态会忽略加载中的阶段,应该结合connectionState来处理不同场景。
修正后的完整代码
class YourPage extends StatefulWidget { @override _YourPageState createState() => _YourPageState(); } class _YourPageState extends State<YourPage> { // 提前在initState里初始化Future,避免重复请求 late Future<List<CustomJsonObject>> _dataFuture; @override void initState() { super.initState(); _dataFuture = _getMyListOfCustomJsonObjects(); } Future<List<CustomJsonObject>> _getMyListOfCustomJsonObjects() { // 这里替换成你的实际API请求逻辑 return Future.delayed(const Duration(seconds: 2), () { return [ CustomJsonObject(Name: "Item 1"), CustomJsonObject(Name: "Item 2"), CustomJsonObject(Name: "Item 3"), ]; }); } @override Widget build(BuildContext context) { return Scaffold( body: CustomScrollView( slivers: [ const SliverAppBar( title: Text("Sliver List Demo"), pinned: true, ), FutureBuilder<List<CustomJsonObject>>( // 使用提前初始化的Future,避免重复请求 future: _dataFuture, builder: (context, snapshot) { // 处理加载中状态 if (snapshot.connectionState == ConnectionState.waiting) { return SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.only(top: 50), child: Stack( alignment: Alignment.bottomCenter, children: [ CircularProgressIndicator( strokeWidth: 4, backgroundColor: const Color(0xFFe5ac3b), semanticsLabel: "Loading", valueColor: const AlwaysStoppedAnimation<Color>(Color(0xFF12336c)), ), ], ), ), ); } // 处理错误状态 else if (snapshot.hasError) { return SliverToBoxAdapter( child: Center(child: Text("加载出错啦: ${snapshot.error}")), ); } // 数据加载完成且不为空 else if (snapshot.hasData && snapshot.data!.isNotEmpty) { return SliverFixedExtentList( itemExtent: 150, delegate: SliverChildBuilderDelegate( (context, index) { final item = snapshot.data![index]; return Container( color: Colors.red, child: Center(child: Text(item.Name)), ); }, childCount: snapshot.data!.length, ), ); } // 空数据状态 else { return const SliverToBoxAdapter( child: Center(child: Text("暂无数据")), ); } }, ), ], ), ); } } // 假设你的CustomJsonObject类是这样的 class CustomJsonObject { final String Name; CustomJsonObject({required this.Name}); }
关键修改点详解
- 提前初始化Future:在
initState里创建_dataFuture,确保API请求只执行一次,这不仅避免了重复请求,还解决了"Duplicate GlobalKeys"的错误。 - 用SliverToBoxAdapter包裹普通Widget:所有非Sliver组件(比如加载指示器、空状态文本)都需要用
SliverToBoxAdapter包裹,才能被CustomScrollView识别为合法的sliver子组件。 - 完善状态处理:新增了加载中、错误、空数据的状态分支,让界面逻辑更完整,用户体验更好。
- 指定FutureBuilder泛型:明确
FutureBuilder<List<CustomJsonObject>>的泛型,让snapshot.data的类型更清晰,代码更安全。
这样修改后,你的SliverFixedExtentList就能正常用Future返回的数据填充,之前的两个错误也能彻底解决啦!
内容的提问来源于stack exchange,提问作者AustinT56
相关产品推荐
相关产品推荐

