Flutter问题:对象列表填充过晚引发CardSwiper断言错误
问题根源
组件构建时,readFile()异步加载数据还没完成,ExampleCandidateModel.candidates是空列表,导致cards列表为空,CardSwiper因为没有卡片触发断言错误。虽然后续数据加载完成,但静态列表更新不会触发组件重建,页面依然报错。
解决方案
方案1:将卡片列表改为组件状态变量,异步加载后触发重建
- 在组件状态类中定义卡片列表的状态变量,替代原来直接映射静态列表的写法。
- 异步加载数据完成后,通过
setState()更新状态,触发组件重建,让CardSwiper拿到有效数据。
修改后代码示例:
class _ExamplePageState extends State<ExamplePage> { List<ExampleCard> _cards = []; @override void initState() { super.initState(); _loadCards(); // 调用异步加载方法 } Future<void> _loadCards() async { final data = await rootBundle.loadString('assets/qa_list.txt'); final lines = const LineSplitter().convert(data); List<ExampleCandidateModel> candidates = []; for (final line in lines) { final words = line.split('*'); final q = ExampleCandidateModel( index: int.parse(words[0].trim()), message: words[1].trim(), color: getColors(words[2].trim()), ); candidates.add(q); } // 更新状态,触发组件重建 setState(() { _cards = candidates.map((candidate) => ExampleCard(candidate)).toList(); }); } @override Widget build(BuildContext context) { // 数据未加载完成时显示加载状态 if (_cards.isEmpty) { return const Center(child: CircularProgressIndicator()); } return CardSwiper( cards: _cards, // 其他配置参数 ); } }
方案2:使用FutureBuilder处理异步加载
直接在build方法中用FutureBuilder管理异步加载状态,无需手动调用setState():
class _ExamplePageState extends State<ExamplePage> { Future<List<ExampleCard>> _fetchCards() async { final data = await rootBundle.loadString('assets/qa_list.txt'); final lines = const LineSplitter().convert(data); List<ExampleCandidateModel> candidates = []; for (final line in lines) { final words = line.split('*'); final q = ExampleCandidateModel( index: int.parse(words[0].trim()), message: words[1].trim(), color: getColors(words[2].trim()), ); candidates.add(q); } return candidates.map((candidate) => ExampleCard(candidate)).toList(); } @override Widget build(BuildContext context) { return FutureBuilder<List<ExampleCard>>( future: _fetchCards(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } else if (snapshot.hasError) { return Center(child: Text('加载失败: ${snapshot.error}')); } else if (!snapshot.hasData || snapshot.data!.isEmpty) { return const Center(child: Text('暂无卡片数据')); } return CardSwiper( cards: snapshot.data!, // 其他配置参数 ); }, ); } }
注意事项
- 避免用静态列表存储需要动态加载的组件数据,静态变量无法触发组件状态更新,会导致UI和数据不同步。
- 必须在数据加载完成前给
CardSwiper提供非空列表,或者显示加载/空状态,避免触发断言错误。
内容的提问来源于stack exchange,提问作者fluttergogo
相关产品推荐
相关产品推荐

