Dart中List转Map<Sub, Padding>时出现Iterable类型不匹配问题
Dart类型不匹配问题排查与解决
问题重现
报错提示:参数类型'Iterable<Map<Sub, Padding>>'无法分配给参数类型'Map<Sub, Padding>'
CupertinoSegmentedControl 使用代码
CupertinoSegmentedControl<Sub>( groupValue: _subView, onValueChanged: (Sub newSelection) { setState(() { _subView = newSelection; }); }, children: _segment(context), )
_segment 方法实现代码
Map<Sub, Padding> _segment(BuildContext context) { List<ProductDetails> productsSorted = _products ..sort((a, b) { return a.rawPrice.compareTo(b.rawPrice); }); Map<Sub, Padding> productList = <Sub, Padding>{}; productList.addAll(productsSorted.map( (ProductDetails productDetails) { return {productsSorted[0] == productDetails ? Sub.weekly : productsSorted[1] == productDetails ? Sub.monthly : Sub.months3 : Padding( padding: const EdgeInsets.symmetric(vertical: 20.0, horizontal: 5.0), child: Column( children: [ Text( productsSorted.last == productDetails ? '3' : '1', style: const TextStyle(fontSize: 22.0), ), Text(productsSorted[0] == productDetails ? Localization.of(context).week : productsSorted[1] == productDetails ? Localization.of(context).month : Localization.of(context).months), const SizedBox(height: 4.0), Text(productDetails.price), productsSorted[0] == productDetails ? const SizedBox() : productsSorted[1] == productDetails ? Text( '-%${_discountCalculator(productsSorted[0].rawPrice, productDetails.rawPrice, 4)}') : Text( '-%${_discountCalculator(productsSorted[0].rawPrice, productDetails.rawPrice, 12)}'), ], ), )}; }, )); return productList; }
错误原因
productsSorted.map() 返回的是 Iterable<Map<Sub, Padding>>——即一组仅包含单个键值对的小Map。但 Map.addAll() 仅接受两种参数类型:
- 同类型的完整
Map<K,V> - 由
MapEntry<K,V>组成的可迭代集合
直接传入 Iterable<Map<Sub, Padding>> 会触发类型不匹配错误。
修复方案
方案一:用 expand 展开Map的entries
将 map 替换为 expand,把每个小Map的键值对展开为 MapEntry 集合,让 addAll 可以正确处理:
productList.addAll(productsSorted.expand((ProductDetails productDetails) { return { productsSorted[0] == productDetails ? Sub.weekly : productsSorted[1] == productDetails ? Sub.monthly : Sub.months3: Padding( // 原Padding内容保持不变 ) }.entries; }));
方案二:用 forEach 直接赋值(更直观)
抛弃 map 和 addAll,直接遍历排序后的列表,逐个往目标Map中添加键值对,逻辑更清晰:
Map<Sub, Padding> _segment(BuildContext context) { List<ProductDetails> productsSorted = _products ..sort((a, b) => a.rawPrice.compareTo(b.rawPrice)); Map<Sub, Padding> productList = <Sub, Padding>{}; for (final productDetails in productsSorted) { final Sub subType; if (productsSorted[0] == productDetails) { subType = Sub.weekly; } else if (productsSorted[1] == productDetails) { subType = Sub.monthly; } else { subType = Sub.months3; } productList[subType] = Padding( padding: const EdgeInsets.symmetric(vertical: 20.0, horizontal: 5.0), child: Column( children: [ Text( productsSorted.last == productDetails ? '3' : '1', style: const TextStyle(fontSize: 22.0), ), Text(productsSorted[0] == productDetails ? Localization.of(context).week : productsSorted[1] == productDetails ? Localization.of(context).month : Localization.of(context).months), const SizedBox(height: 4.0), Text(productDetails.price), productsSorted[0] == productDetails ? const SizedBox() : productsSorted[1] == productDetails ? Text('-%${_discountCalculator(productsSorted[0].rawPrice, productDetails.rawPrice, 4)}') : Text('-%${_discountCalculator(productsSorted[0].rawPrice, productDetails.rawPrice, 12)}'), ], ), ); } return productList; }
内容的提问来源于stack exchange,提问作者Cenk YAGMUR
相关产品推荐
相关产品推荐

